Author: Big move

This article is an original article, please indicate the author and the author

background

In order to support CCtalk’s functions such as watching live video and real-time chat on the Web, the traditional short connection cannot realize the purpose of real-time push, and a long connection needs to be established. However, the cost of establishing a connection for Web users is very low, and the resource consumption of long connection is large, so the framework needs to have enough support for large concurrency. Netty + Websocket is a good solution for large concurrency and long connections, so the next three articles will cover this in detail.

  1. The principle of article

  2. Application of article

  3. WebSocket

Abstract

The first two articles respectively to introduce the principle, application, this time to introduce the application of WebSocket in Netty.

What is the WebSocket

The traditional HTTP protocol can only be initiated by the client, but not by the server. There may be some people who say that long polling can be used, that is, the client side constantly requests the server side to obtain new data. Although it can solve the problem, it is inefficient and wastes resources, which can only be said to be a stupid method. So websockets came into being.

WebSocket protocol was born in 2008 and became an international standard in 2011, supported by all browsers. The most important feature is the full-duplex communication between the server and the client. That is, the client can send messages to the server, and the server can also send messages to the client.

The default port 80 or 443 protocol identifier is WS (or WSS if encrypted) and the server URL is the URL, for example:

ws://example.com:8080/path

Both HTTP and Websocket are based on TC P protocol, as shown below:

The difference lies in the interaction process with the server, as shown in the following figure:

As you can see from the figure, traditional HTTP has only request and response, whereas WebSocket has these phases.

  1. Handshake stage

  • The client sends a handshake request with the following packets:

    Upgrade and Connection indicate that the WebSocket protocol is currently initiated.

    Sec-websocket-key is a Base64 encode value that the browser randomly generates to verify that the server supports the WebSocket protocol

    Sec_websocket-protocol This parameter is user-defined based on services, and is specified in the URL

  • The server responds to the handshake request with the following packet:

    Sec-websocket-accept is an encrypted sec-websocket-key that has been authenticated by the server

    It can be seen that the handshake stage adopts HTTP protocol, which can pass various PROXY servers of HTTP and has good compatibility with HTTP protocol.

  1. Long connection stage

    Upgrade from HTTP to Websocket by handshake,

    At this point, you can send any message to the server, and the service can actively push messages to you. The data format can be negotiated with the server according to service requirements, providing high flexibility and high communication efficiency.

  2. The connection closure is initiated by either the client or the server.

WebSocket application

We mainly use Netty framework to achieve the server, using JS to achieve the client.

Server-side implementation

Netty-socketio is an open source framework that encapsulates WebSocket protocol resolution and response. If you are a Maven project, you can add Dependecy to PEM. XML.

<dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.712.</version></dependency>Copy the code

The application is relatively simple, the following code:

public static void main( String[] args ) throws InterruptedException {  final SocketIOServer server = new SocketIOServer(loadSocketIOConfig(doc)); / / (1) / / start the login final SocketIONamespace ns = server.addNamespace("/echo"); / / (2) EchoConnectListener listener = new EchoConnectListener(); / / (3) EchoEventListener evtlistener = new EchoEventListener(); / / (4) ns.addConnectListener(listener); ns.addDisconnectListener(listener); ns.addEventListener(WebEventMessage.EVT_TAG, WebEventMessage.class, evtlistener);  / / (5) server.start(); logger.info("============>WSServer started ... ok"); }private static Configuration loadSocketIOConfig(Document doc) { Configuration config = new Configuration(); config.setHostname(getNodeStr(doc, "host")); config.setPort(getNodeInt(doc, "port")); config.setBossThreads(getNodeInt(doc, "bossThreads")); config.setWorkerThreads(getNodeInt(doc, "workerThreads")); //config.setUseLinuxNativeEpoll(PlatformDependent.isWindows() ? false : true); returnconfig; }Copy the code
public class EchoEventListener implements DataListener<WebEventMessage> {private static final Logger logger = LoggerFactory.getLogger(EchoEventListener.class); public EchoEventListener(a) { }@Override public void onData(SocketIOClient client, WebEventMessage data, AckRequest ackSender) throws Exception { System.out.println("message:" + data.getMessage()); WebEventMessage hello = new WebEventMessage(); JSONObject object = new JSONObject(data.getMessage()); if (UserTokenMgr.getInstance().verify(object.getInt("userid"), object.getString("token"))) { hello.setMessage("login success"); } else { hello.setMessage("login failed"); } client.getNamespace().getBroadcastOperations().sendEvent(WebEventMessage.EVT_TAG, hello); / / (6) }}Copy the code

Note: The Arabic numerals in the sample code correspond to the Arabic numerals in the text description.

  1. Load the configuration, instantiate SocketIOServer, and configure mainly the IP, port, processing thread, and worker thread count.

  2. Add a Namespace named echo. This access is represented in the URL as follows:

    ws://example.com:8080/echo

    Any access to this URL will be handled in this namespace.

  3. Create a connection listener

  4. Create a business message handler

  5. Add a connection listener and a business message handler to a namespace, specifying a message protocol object, such as WebEventMessage, when adding a business message handler.

  6. The server receives the data and returns it to the client.

Client-side implementation

The client here is using socket. IO, using JS implementation, and front-end docking.

var socket = io.connect('http://127.0.0.1:8080/echo'); socket.on('connect', function() { output('Client has connected to the server! '); });/ / (1)socket.on('message', function(data) { output('<span class="username-msg"> echo' + ':</span> '+ data.message); });/ / (2)socket.on('disconnect', function() { output('The client has disconnected! '); });/ / (3)Copy the code

Sending data:

var message = JSON.stringify(jsonmsg); var cmd =1; var jsonObject = {'@class': 'WebEventMessage', cmd:cmd, message: message}; socket.emit('message', jsonObject, function(arg1, arg2) {}); / / (4)Copy the code

Note: The Arabic numerals in the sample code correspond to the Arabic numerals in the text description.

  1. Connect Callback function after the connection is established.

  2. Message is used to specify the callback function to receive server data.

  3. Disconnect Callback function after disconnecting.

  4. Emit sends a message to the server.

conclusion

Netty based Websocket, while providing good performance greatly enhance the live broadcast, chat and other products in the front page experience. CCtalk’s webcast and another product under development use this technology, so you can go to CCtalk (http://www.cctalk.com/) to find a live class. These three articles mainly offer a solution, if there is a better one, or other problems, please feel free to communicate.

Refer to the link

  1. Sokect. IO (https://socket.io/)

  2. Netty – socketio (https://github.com/mrniko/netty-socketio)

  3. WebSocket tutorial (http://www.ruanyifeng.com/blog/2017/05/websocket.html)

Recommendation systems and all that

A story about Nolock

Trading systems – Domain driven design

A crawler framework based on Electron for Nightmare

The translation | Android O seccomp filter