HTML5 New Feature Series: WebSocket

来源:互联网 发布:线切割绘图编程步骤 编辑:程序博客网 时间:2024/06/07 02:34

Nowadays Web Application becomes increasingly complex, hence, message pushing is playing an vital role in Web App functionalities. With message pushing, Web page will be able to receive the message from server timely, then provide the best experience for user. Previously we used the PULL request way to fetch data from server when implementing the message pushing, and this approach is not easy to be perfect, also the logic is comparatively complex.

So, in order to solve this problem, and implement the real message pushing, HTML5 has defined a new standard, that is the WebSocket API. Now Let's take a look at this new feature.

WebSocket is a kind of mechanism which is used to implement a two-way connection with a high performance between server and client, using WebSocket we can easily send and receive message via one HTTP connection. Firstly we need to send a HTTP request to create a connection with server, and server will confirm the protocol and origin, then return client a response, after receiving the response, a WebSocket has been established successfully.

Then how do we send the request on client side? At first we need to instantiate a WebSocket object, as the following code shows:

var socket = new WebSocket('ws://www.websocket-testing.com:9000/server', 'subprotocol');

In the constructor above, the first parameter is the URL which needs to connect with, and the second is the sub protocol name. Note that we can choose any sub protocol from 'ws://' and 'wss://', and they use the 80 and 443 separately as their own default port, if choose the latter, we can encrypt the message with TLS. And also, the second parameter can be an array that contains several sub protocols.

After the constructor's invocation has completed, a connection will be established inside the communication, once connection is successful, the 'open' event of WebSocket will be triggered:

socket.onopen = function(e) {console.log('websocket connection has established');}
Then we can send and receive message, now we will call the 'send' method to send message to server, and capture the 'message' event to receive the message from server:

//send message to websocket serversocket.send('hello, server');//receive message from websocket serversocket.onmessage = function(e){//obtain the message from servervar message = e.data;//do something}
In above code, we sent a message of String type to server, then when receiving message from server, we obtained the message content from the data property of event object. At present, WebSocket can use three message types, String, Blob and ArrayBuffer, the latter two are used to send and receive binary data, but in daily development, the String type can easily meet our demand, if we want to send a JavaScript object data, we just need one extra processing, converting the object to JSON string, and if the message is from server, only thing we need to do firstly is to parse the string to a JavaScript object.
After the communication completed, client can call 'close' method to cut off the connection with server, once it's disconnected, the 'close' event will be invoked, we can capture this event to do further processings:
//cut off the connectionsocket.close();socket.onclose = function(e){//do something}
On occasion, due to the server's shutdown, our client will lose the connection, at this time we can attempt to reconnect by capturing the 'close' event, just as the code shows below:
socket.onclose = function() {setTimeout(function() {//reconnect operation}, 100000);}

If new client attempts to establish a connection with the server which has been down, it will make a failure in this case, at this time the error event will be triggered, we can capture this error event to do some corresponding operations.

socket.onerror = function() {    console.log('socket error occurred');};
It should be noted that when client fails to connect, the error and close events will be triggered in order, so we need to avoid the overlap in real development.

And then, in order to show the best of the interaction process of WebSocket, we will create a simple online chatting program including server and client.

Server side

To create a chatting program, in the first place we need to set up the server environment, and make it support WebSocket communication, very luck, currently most programming languages have their own libraries related to WebSocket, we can choose one according to our own familiarity, here we will use Node.js platform to set up a simple server. There are many powerful libraries on Node.js platform, here in order to illustrate the basic usage of WebSocket, we pick up a simple library named 'ws', and use the 'npm' command to install it:

npm install ws
If anyone is not familiar with this library, may take a look at it on github: https://github.com/websockets/ws.
And then we will create and run a simple server, after the installation, we just need to create a file named 'websocket-server.js' under the same folder of generated 'node_modules', as the picture shows:


And a simple code snippet in websocket-server.js shows below:

var WebSocketServer = require('ws').Server;var socketServer = new WebSocketServer({ port: 9000 });//to store all connected clientsvar clients = [];socketServer.on('connection', function(socket) {//if not the specified origin, disconnect the socketvar origin = socket.upgradeReq.headers.origin;if (origin !== 'http://localhost') {socket.close();return;}//add to clients when socket is connectedclients.push(socket);//broadcast to clients when new message comes from one clientsocket.on('message', function(message) {console.log(message);clients.forEach(function(client) {if (client !== socket) {client.send(message);}});});//remove from clients when socket is offline or disconnectedsocket.on('close', function() {for (var i = 0; i < clients.length; i++) {var client = clients[i];if (client === socket) {clients.splice(i, 1);}}});});console.log('socketServer is listening on 9000...');
In the code, we firstly created an independent running WebSocket service, listening on port 9000 to receive cient's request, and when client is connected, server will push client to 'clients' after the security verification, and when one client sends a message, server will broadcast this message to other clients, at last when client is disconnnected with server, it will be removed from 'clients'.
Then how do we run this server? Just one command below:
node websocket-server.js

Client side

After the server has set up, let's continue to implement the client. On client side, we will create a chatting window which contains a message display area and typing area, we can type in messages and send them to server, then server will broadcast to other clients, each client will append the new message to message display area when receiving it. Now let's take a look at the UI view in client:


And here is the html structure of client page:

<html><head><title>WebSocket</title><link rel="stylesheet" type="text/css" href="css/main.css"></head><body><div id="chatting-room"><div class="description">chattings</div><div id="chatting-messages"><!-- chatting messages will be here --></div><div class="input-container"><div id="chatting-input" contenteditable></div></div><div class="action-container"><button onclick="sendMessage();">Send</button></div></div><script type="text/javascript" src="js/jquery.js"></script><script type="text/javascript" src="js/main.js"></script></body></html>
In the code above we can see button binds a 'click' event, so clicking the button will call 'sendMessage' function, and then message will be sent. And messages from server will be showing in #chatting-messages area.

As we all know, the communication between client and server is based on WebSocket, so first of all, we need to create a WebSocket instance:

window.username = prompt('please input your name') || 'scott';//connect to a socket serverwindow.socket = new WebSocket('ws://localhost:9000');//capture open eventsocket.onopen = function() {console.log('socket connected');};//capture message eventsocket.onmessage = function(e) {appendMessage(JSON.parse(e.data), false);};//capture close eventsocket.onclose = function(e) {console.log('socket disconnected');};
In this code snippet, we required user to input their name before the chatting, and then created a WebSocket instance, then registered relevant events, in 'onmessage' function we notice that 'appendMessage' is called, this function is responsible for appending a message to message display area, now let's take a look at the 'appendMessage' and 'sendMessage' function:

//append message to chatting-messages areafunction appendMessage(data, isSelf) {var message = '<img class="icon" src="img/icon.png">'+ '<div class="message">'+ '<span class="message-name">' + data.name + '</span>'+ '<div class="message-content">' + data.message + '</div>'+ '</div>';var messageBody = $('<div class="message-body"></div>');if (isSelf) {messageBody.addClass('message-self');}messageBody.html(message);$('#chatting-messages').append(messageBody);}//collect user's input and send the message to serverfunction sendMessage() {var editArea = $('#chatting-input'),message = editArea.text().trim();if (!message) return;var messageObject = {name: window.username, message: message};window.socket.send(JSON.stringify(messageObject));appendMessage(messageObject, true);editArea.html('');}
In the 'appendMessage' function, we specified two parameters, first one is the message need to append which contains username and message content, and the second is for distinguishing if the message is sent by self, if it is, message will be appended to right side of the window, if not, left side instead. The 'sendMessage' function is responsible for collecting user's input, and converting them into JSON string, then sending the string to server via WebSocket, meanwhile, appending the message to message display area.

That's all of the WebSocket explain, if in real development, we can easily build a real time two-way messaging system with high performance by working with server and unifying the data and event handling, and then implement a real sense of Web message pushing. 

Thanks all for reading, hopefully it's helpful to you. :)


1 0
原创粉丝点击