HTML 5 – Tìm hiểu WebSocket và Node.js

Trong bài này, ta sẽ tìm hiểu sơ lược về công nghệ WebSocket cùng cách hiện thực nó với Node.js và thư viện Socket.io.

WebSocket là gì?

WebSoket là công nghệ hỗ trợ giao tiếp hai chiều giữa client và server bằng cách sử dụng một TCP socket để tạo một kết nối hiệu quả và ít tốn kém. Mặc dù được thiết kế để chuyên sử dụng cho các ứng dụng web, lập trình viên vẫn có thể đưa chúng vào bất kì loại ứng dụng nào.

Dữ liệu truyền tải thông qua giao thức HTTP (thường dùng với kĩ thuật Ajax) chứa nhiều dữ liệu không cần thiết trong phần header. Một header request/response của HTTP có kích thước khoảng 871 byte, trong khi với WebSocket, kích thước này chỉ là 2 byte (sau khi đã kết nối).

Vậy giả sử bạn làm một ứng dụng game có thể tới 10,000 người chơi đăng nhập cùng lúc, và mỗi giây họ sẽ gửi/nhận dữ liệu từ server. Hãy so sánh lượng dữ liệu header mà giao thức HTTP và WebSocket trong mỗi giây:
– HTTP: 871 x 10,000 = 8,710,000 bytes = 69,680,000 bits per second (66 Mbps)
– WebSocket: 2 x 10,000 = 20,000 bytes = 160,000 bits per second (0.153 Kbps)
Như bạn thấy chỉ riêng phần header thôi cũng đã chiếm một phần lưu lượng đáng kể với giao thức HTTP truyền thống.

Giao thức bắt tay của WebSocket

Để thực hiện kết nối, client phải gửi một WebSocket handshake request đến server. Server sẽ gửi trả lại WebSocket handshake response như bên dưới:

Client request:

GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

Server response:(Server Architecture)

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Để xác nhận việc kết nối, client sẽ gửi một giá trị Sec-WebSocket-Key được mã hóa bằng Based64 đến server. Sau đó bên server sẽ thực hiện:
– Nối thêm chuỗi cố định là “258EAFA5-E914-47DA-95CA-C5AB0DC85B11″ vào Sec-WebSocket-Key để được chuỗi mới là “x3JJHMbDL1EzLkh9GBhXDw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11″.
– Thực hiện mã hóa SHA-1 chuỗi trên để được “1d29ab734b0c9585240069a6e4e3e91b61da1969″.
– Mã hóa kết quả vừa nhận được bằng Base64 để được “HSmrc0sMlYUkAGmm5OPpG2HaGWk=”.
– Gửi response lại client kèm với giá trị Sec-WebSocket-Accept chính là chuỗi kết quả vừa tạo ra.
Client sẽ kiểm tra status code (phải bằng 101) và Sec-WebSocket-Accept xem có đúng với kết quả mong đợi không và thực hiện kết nối.

WebSocket với Node.js và Socket.IO

NodeJs

Socket.IO là một thư viện javascript có mục đích tạo ra các ứng dụng realtime trên trình duyệt cũng như thiết bị di động. Việc sử dụng thư viện này cũng rất đơn giản và giống nhau ở cả server lẫn client. Trong ví dụ tôi sắp trình bày, bạn sẽ thấy server và client sử dụng Socket.IO gần như giống nhau. Điều này giúp cho việc tiếp cận nó trở nên rất dễ dàng nếu bạn đã quen thuộc với javascript.

Download và cài đặt: http://nodejs.org/#download
Nếu bạn sử dụng Windows như tôi, có thể download trực tiếp tại: http://nodejs.org/dist/v0.6.19/node-v0.6.19.msi
Sau đó cài mở cửa sổ console và cài đặt Socket.io bằng lệnh sau:

npm install socket.io

Tìm hiểu về Socket.IO

Với Node.js, bạn chỉ cần biết vài hàm cơ bản như requires() để import thư viện. Công việc còn lại, chỉ cần dùng Socket.IO nên bạn cần phải tìm hiểu về thư viện này tại đây: http://socket.io/#how-to-use.

Nếu lười tìm hiểu, bạn có thể xem qua vài dòng lý thuyết dưới đây:
– Server: tạo một đối tượng socket bằng phương thức listen(port). Phương thức này chờ đợi một yêu cầu kết nối từ client.
– Client: Kết nối đến server bằng phương thức connect(url,{port: server_port}).
– Socket.IO cung cấp 3 event chính là connect, message và disconnect. Chúng được kích hoạt khi client/server:
+ connect: tạo kết nối
+ message: nhận được thông điệp
+ disconnect: ngắt kết nối
Ví dụ:
socket.on(“message”, function(msg){
// console.log(“Received: “+ msg);
});

– Để gửi dữ liệu, ta dùng phương thức send().Dữ liệu có thể là đối tượng (được chuyển thành chuỗi json) và sẽ nhận được qua sự kiện message.
Ví dụ: socket.send(“Hello world”);
– Socket.IO có thể gửi và nhận các event tự tạo với phương thức emit(). Hai phía gửi và nhận phải biết được tên của event đó để thực hiện giao tiếp:

Ví dụ:
// send:
socket.emit(“hello”,{msg: “welcome”);
// receive:
socket.on(“hello”, function (data) {
console.log(data);
}
);

OK, bạn đã có đủ các kiến thức cơ bản để bắt đầu.

Ví dụ

Trong ví dụ này, tôi sẽ tạo một ứng dụng cho phép client gửi các chuỗi biểu thức toán đến server. Server sẽ tính kết quả và trả về cho client.
Server:
Tạo một tập tin server.js với nội dung sau:

var io = require('socket.io');

var socket = io.listen(5555);
socket.sockets.on('connection',function(socket){
        socket.on('message', function(expr){
            console.log('Received expression from client ',expr);
			// catch error for bad expression
			try{
				socket.send(eval(expr));
			}catch(err){
				socket.emit("error",err.message);
			}
        });
        socket.on('disconnect', function(){
            // console.log('Disconnected');
        });
});

Sau đó bạn chạy server bằng cách vào cửa sổ console gõ lệnh (:
node [path to js file]

Do tôi chuyển đến thư mục chứa file js nên chỉ cần gõ:
node server.js

Client:

<html>
	<head>
	<title>WebSocket Client</title>
	<script src="http://localhost:5555/socket.io/socket.io.js"></script>
	<script>
	window.onload = function(){
		var input = document.getElementById('input');
		var output = document.getElementById('output');

		var socket = io.connect('localhost',{port: 5555});

		socket.on("connect",function(){
			console.log("Connected to the server");
		});
		socket.on('message',function(data) {
			output.innerHTML = '=' + data;
		});
		socket.on('error', function (data) {
			console.log("error:",data);
		   }
		);

		window.sendMessage = function(){
			socket.send(input.value);
		};
	}

    </script>
	</head>
    <body>
		<input type='text' id='input' />
		<span id='output'></span>
		<br/>
		<input type='button' id='send' value='calc' onclick='sendMessage();' />
	</body>
</html>

Kết quả:

WebSocket Client Demo

Tài liệu tham khảo:

WebSocket: http://en.wikipedia.org/wiki/WebSocket

HTML5 Web Socket in Essence: http://www.codeproject.com/Articles/209041/HTML5-Web-Socket-in-Essence

The WebSocket protocol: http://tools.ietf.org/html/rfc6455

The WebSocket API: http://www.w3.org/TR/websockets/

Socket IO: http://socket.io/#how-to-use

Node.js Documentation: http://nodejs.org/api/

Nguồn: YinYangIt’s Blog