Node.js实现WebSocket客户端

笔者在工作中闹出了用nodejs的net.socket连接WebSocket服务器的笑话,故写文记录WebSocket的有关信息,并给出在nodejs实现WebSocket客户端的方法。

WebSocket与socket的区别

  • WebSocket是一种双向通信协议,客户端和服务器都可以发送和接收数据。socket不是协议,只是一组应用层和传输层的接口。
  • WebSocket在应用层,建立在TCP连接上。socket在传输层,是用于建立TCP连接的。socket对复杂的TCP/IP协议进行了封装,便于开发者实现TCP通信的功能。

net.socket

此类是 TCP socket 或流式 IPC 端点的抽象。 详见

故net.socket是nodejs中用于实现socket通信的工具类,与WebSocket无关。

关于WebSocket

WebSocket的作用

WebSocket是一种基于TCP的应用层协议,实现了客户端和服务器的全双工通信,使得客户端和服务器都能主动向对方发送数据。一旦WebSocket连接建立,后续数据都以帧序列的形式在同一持久连接上传输,节省了网络带宽。
WebSocket适用于服务端不断有数据更新,而客户端需要及时获取数据更新的情况。只用HTTP的话,客户端为了实时显示数据更新,需要每隔一小段时间就发起一次HTTP请求获取数据,来检查是否更新。而使用WebSocket后,服务端在数据更新后可以将更新的数据通过WebSocket连接通知客户端,实现开销较小的实时显示。

WebSocket连接的建立过程

  1. 客户端和服务器通过三次握手建立TCP连接。
  2. TCP连接成功后,客户端通过HTTP协议向服务端传送WebSocket支持的版本号等信息。
  3. 服务端收到握手请求后,同样采用HTTP回复数据。
  4. 当收到连接成功的信息后,客户端和服务器通过TCP通道进行传输通信。

WebSocket的实现

客户端 - 在浏览器中运行

直接使用JS的WebSocket对象创建新的WebSocket实例并连接。连接与回调设置代码如下:

var ws = new WebSocket('ws://localhost:8080');
  ws.onopen = function(e){
    console.log("连接服务器成功");
    // 向服务器发送消息
    ws.send("what`s your name?");
  }
  ws.onclose = function(e){
    console.log("服务器关闭");
  }
  ws.onerror = function(){
    console.log("连接出错");
  }
  // 接收服务器的消息
  ws.onmessage = function(e){
    let message = "message:"+e.data+"";
    console.log(message);
  }

需要注意的是:JS的WebSocket对象只能在浏览器环境中访问。详见这里

客户端 - 不在浏览器中运行

以下方法也可以在Electron的main进程中实现WebSocket客户端

WebSocket-Node

WebSocket-Node
使用WebSocket-Node创建WebSocket连接并设置回调的代码如下:

var WebSocketClient = require('websocket').client;

var client = new WebSocketClient();

client.on('connectFailed', function(error) {
    console.log('Connect Error: ' + error.toString());
});

client.on('connect', function(connection) {
    console.log('WebSocket Client Connected');
    connection.send("what`s your name?");
    connection.on('error', function(error) {
        console.log("Connection Error: " + error.toString());
    });
    connection.on('close', function() {
        console.log('echo-protocol Connection Closed');
    });
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log("Received: '" + message.utf8Data + "'");
        }

    });
    
    function sendNumber() {
        if (connection.connected) {
            var number = Math.round(Math.random() * 0xFFFFFF);
            connection.sendUTF(number.toString());
            setTimeout(sendNumber, 1000);
        }
    }
    sendNumber();
});

//下面不能加'echo-protocol',否则会报Can`t connect due to "Sec-WebSocket-Protocol header"的错。因为服务器没有返回对应协议规定的信息
client.connect('ws://localhost:8080/'); //, 'echo-protocol');
ws

ws
安装:
https://github.com/websockets/ws
使用ws创建WebSocket连接并设置回调的代码如下:

var ws = require("ws");
 
// url ws://127.0.0.1:6080
// 创建了一个客户端的socket,然后让这个客户端去连接服务器的socket
var sock = new ws("ws://localhost:8080/");
sock.on("open", function () {
    console.log("connect success !!!!");
    sock.send("HelloWorld");
});
 
sock.on("error", function(err) {
    console.log("error: ", err);
});
 
sock.on("close", function() {
    console.log("close");
});
 
sock.on("message", function(data) {
    console.log(data);
});

服务端

nodejs-websocket

安装:
npm install nodejs-websocket
创建服务并设置回调函数:

var ws = require("nodejs-websocket")

// Scream server example: "hi" -> "HI!!!"
var server = ws.createServer(function (conn) {
    console.log("New connection")
    conn.on("text", function (str) {
        console.log("Received "+str)
        conn.sendText(str.toUpperCase()+"!!!")
    })
    conn.on("close", function (code, reason) {
        console.log("Connection closed")
    })
}).listen(8001)
ws

创建服务并设置回调函数:

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: %s', message);
  });

  ws.send('something');
});

WebSocket与Socket.io

这是另一个容易混淆的地方。虽然socket.io和WebSocket都支持实时通信,但是它们并不能混用。

Socket.io不是Websocket,它只是将Websocket和轮询 (Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。也就是说,Websocket仅仅是 Socket.io实现实时通信的一个子集。因此Websocket客户端连接不上Socket.io服务端,当然Socket.io客户端也连接不上Websocket服务端。
详见

故如果要使用socket.io进行实时通信,必须同时使用socket.io-client作为客户端,socket.io作为服务端。

你可能感兴趣的:(Node.js实现WebSocket客户端)