每天看一片代码系列(二):WebSocket-Node
簡介
我們都知道,websocket主要是通過在瀏覽器和服務端建立長連接,繼而實現二者的相互數據通信。不同于HTTP的輪詢,它不會有大量無效的HTTP消息交換,從而節省了花銷。websocket其實就是雙通道的TCP連接。
很明顯地,整個工作分為兩個步驟,即創建連接和發送數據。那么連接是怎么建立的呢?其實只需要在瀏覽器和服務器端做一個握手的動作就可以了。而這個握手其實還是一個HTTP請求,只是接下來的工作就和HTTP沒關系了。
這個HandShake的請求消息大致為:
GET /chat HTTP/1.1 Host: example.com:8000 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13而響應的消息大致為:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=HTTP里面的upgrade頭部代表要從HTTP協議切換到另一個協議,或者是更換一個不同版本的HTTP。而Sec-WebSocket-Key和Sec-WebSocket-Accept是用來進行驗證的字段。后者是前者經過一系列操作計算出來的,用來給客戶端判斷響應和請求是否匹配。
使用WebSocket-Node
首先我們體驗一下“websocket-node"這個庫的用法。
其實用這個庫就是為了創建一個websocket-server,在app.js中,我們創建即可。
var port = 3001; var websocketServer = require('websocket').server; var http = require('http');// 創建httpServer var httpServer = http.createServer(); httpServer.listen(port, function () {console.log(new Date() + " Http Server is listening on " + port); });//創建WebSocketServer var wsServer = new websocketServer({httpServer: httpServer });wsServer.on('request', function (request) {console.log(new Date() + " connection from origin: " + request.origin + ' .');//建立連接var connection = request.accept('example', request.origin);//向客戶端發送消息connection.sendUTF("Connection from " + request.origin);connection.on('close', function () {console.log(connection.remoteAddress + " disconnected.");})//收消息connection.on('message', function (message) {try{connection.sendUTF("Server accpected: " + message.utf8Data);}catch(e){}}) })在瀏覽器中,就和這個庫沒什么關系了,直接用瀏覽器支持的API創建Websocket客戶端,收發消息即可。
var wsServer = "ws://localhost:3001"; var ws = new WebSocket(wsServer, 'example');ws.onopen = function (e) {var msg = "hello Server!";ws.send(msg) && print(msg); }ws.onclose = function (e) {var msg = "closed connection";print(msg); }ws.onmessage = function (e) {var msg = "received : " + e.data;print(msg); }源碼解析
源碼有多個文件,我們只關注WebSocketServer.js,地址
首先,在傳入的配置中必須要綁定一個httpServer用于握手。當客戶端建立連接時,首先會進行握手,會觸發server的upgrade事件,從而進入到服務端的處理函數中去。在這個函數中,會創建一個wsRequest對象,并將它作為request事件的參數發送出去。接下來根據客戶端的Accept情況來進入到handleRequestAccepted,接下來connect事件會被觸發。
var upgradeHandler = this._handlers.upgrade; this.config.httpServer.forEach(function(httpServer) {httpServer.on('upgrade', upgradeHandler); });handleUpgrade: var wsRequest = new WebSocketRequest(socket, request, this.config); try {wsRequest.readHandshake(); } wsRequest.once('requestAccepted', this._handlers.requestAccepted);wsRequest.once('requestResolved', this._handlers.requestResolved); if (!this.config.autoAcceptConnections && utils.eventEmitterListenerCount(this, 'request') > 0) {this.emit('request', wsRequest); }handleRequestAccepted: this.connections.push(connection); this.emit('connect', connection);另外,WebsocketServer繼承了EventEmitter,所以具有事件處理的能力:
util.inherits(WebSocketServer, EventEmitter);?
轉載于:https://www.cnblogs.com/cubika/p/4437901.html
總結
以上是生活随笔為你收集整理的每天看一片代码系列(二):WebSocket-Node的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 博客美化20150418
- 下一篇: iOS开发:iPhone6、6 plus