Html5 – WebSocket và Node.js

Html5 WebSocketTrong 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

Node.js đang là một nền tảng được xây dựng trên Chrome’s JavaScript runtime để tạo các ứng dụng network với ngôn ngữ javascript. Như vậy, javascript không bị giới hạn bên trong trình duyệt và ở phía client. Việc sử dụng javascript làm server giúp lập trình viên không cần sử dụng các ngôn ngữ Server-Side như Perl, PHP, ASP.NET, Python, JSP,… mà còn giúp họ tận dụng được những thế mạnh của javascript.

SocketIO

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

Đọc thêm

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/

YinYangIt’s Blog

Advertisements

25 thoughts on “Html5 – WebSocket và Node.js

  1. Mình cũng start đc server rồi, nhưng khi nhấn calc thì không thấy gì hết, server cũng nhận đc message rồi :(. Có gì giúp mình hen

    info – socket.io started
    debug – served static /socket.io.js
    debug – client authorized
    info – handshake authorized 2126656944374657859

    • Sao mình không start được server nhỉ,
      Nó cứ báo thế này:
      C:\Users\10520_000>node d:\server.js
      module.js:340
      throw err;
      ^
      Error: Cannot find module ‘socket.io’
      at Function.Module._resolveFilename (module.js:338:15)
      at Function.Module._load (module.js:280:25)
      at Module.require (module.js:362:17)
      at require (module.js:378:17)
      at Object. (d:\server.js:1:72)
      at Module._compile (module.js:449:26)
      at Object.Module._extensions..js (module.js:467:10)
      at Module.load (module.js:356:32)
      at Function.Module._load (module.js:312:12)
      at Module.runMain (module.js:492:10)

  2. ở đây có pro nào thực sự hiểu công nghệ đằng sau Nodejs hay mấy thứ real-time dạng này mới nổi.
    Theo em hiểu kết nối truyền thống là client request đến server,chờ server response thì đóng kết nối.Vậy Node js có phải giữ cho kết nối này luôn mở???
    Vậy tại sao ngày xưa vấn đề giữ kết nối ko được lưu tâm mà phải đợi đến tận bây giờ?
    Vậy nếu trong vô vàn kết nối đến server,Nodejs server làm thế nào biết kết nối nào cần dữ liệu mới để push về cho nó???
    Và như vậy thì giao thức websocket cũng sẽ làm được vấn đề này?Vậy ta cần j ở Nodejs??
    Mong các pro thông giùm

  3. Anh cho em hỏi vậy có cách nào tiếp cận với websocket mà ko dùng node.js không. Vì nếu mà đã sử dụng websocket thì ta có thể viết game, ứng dụng, web v.v.v mà điều này hay phải dùng đến database, javascript không hỗ trợ được tốt trong vấn đề này. Mong anh trả lời giúp

  4. Nếu trực tiếp áp dụng vào thẳng vấn đề thực tế là trò mario anh vừa hướng dẫn lúc trước muốn chơi giữa 2 người qua mạng thì áp dụng cái này như thế nào hả anh? Nó gồm những bước nào giải quyết mong anh trả lời giúp ạ

    • Vậy thì game cần phải liên tục cập nhật các trạng thái của nhân vật lên server và đồng bộ với các người chơi khác. Vấn đề này mình cũng ko có kinh nghiệm nên ko tiện chia sẻ nhiểu.

  5. Pingback: http://www.sitepoint.com/chat-application-using-socket-io/ | ghinho

  6. Chào ad,mình muốn lấy một thông báo khi có một bài đăng mới trên web ,không biết web socket này có thể giúp mình giải quyết vấn đề trên không ,xin cám ơn đã đọc câu hỏi này,mong nhận được câu trả lời sớm!

  7. Chào bạn, mình muốn hỏi bạn 1 câu là Websocket có thể kết nối server và clinet ở 2 đường mạng khác nhau k bạn, ví dụ client ở Việt Nam, còn server ở Mỹ chẳng hạn. Vì theo mình đc biết Socket chỉ kết nối được trong cùng đường mạng (sorry nếu mình hiểu sai)

  8. Anh cho e hỏi là, e dc bạn bày tải wampserver về, viết 2 đoạn code server/client vào notepad.
    sau đó copy 2 cái notepad và cái nodejs vào thư mục www của wampserver.
    rồi mở cmd chạy chương trình. Còn cách làm dễ hơn k?
    cám ơn ạ!

  9. Pingback: Giới thiệu về Websocket và Node.js

Đã đóng bình luận.