IM聊天室(一):WebSocket

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36113598/article/details/78836101

1、什么是WebSocket?它和Socket有什么关系?

在网络中,两个程序(进程)需要全双工通信,即双方可以同时向对方发送消息,需要用到的就是Socket,它能够提供端对端通信。

具体的实现过程如下:

  • 客户端:创建一个Socket实例,并且提供服务端的IP和端口,如:192.168.1.1:8081

  • 服务端:创建另一个Socket并绑定本地端口进行监听,如:localhost:8081

  • 两者约定的端口要相同

  • 客户端对服务端进行请求连接,服务端接受后通知客户端,双方就建立了一个TCP连接

  • 至此,客户端和服务端之间可以进行双向通信,并且无客户端和服务端之分,均为端对端通信,但是主流的IM还是采用服务端转发的方式进行消息传送。

WebSocket借鉴了socket的思想,为web应用程序的客户端和服务端之间提供了一种全双工通信机制(注意:在WebSocket中是有客户端和服务端之分的)。

不同于原生Socket的端到端直接通信,WebSocke采取的方式是让所有客户端连接服务端,服务器再将不同客户端发送给自己的消息进行转发或者广播。

2、Websocket的通信原理

虽然WebSocket是一种新应用层协议,但既然是基于Web端的技术,就无法脱离HTTP而单独存在。但是它和HTTP最大的不同是:

1、WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样

2、WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信


所以当我们构建一个WebSocket实例的时候,实际上过程是这样的:

  • 客户端发送一个 http Get 请求报文,告诉服务端:我要将通信协议切换到WebSocket啦!发送的数据格式类似下面的内容:
GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13

//该请求和普通的HTTP请求有几点不同:
//GET请求的地址不是类似/path/,而是以ws://开头的地址;
//请求头Upgrade: websocket和Connection: Upgrade表示这个连接将要被转换为WebSocket连接;
//Sec-WebSocket-Key是用于标识这个连接,并非用于加密数据;
//Sec-WebSocket-Version指定了WebSocket的协议版本。
  • 如果服务端支持WebSocket协议,那么服务端就会将自己的通信协议切换为WebSocket,同时回传给客户端一个状态码为101的响应报头,该响应代码101表示本次连接的HTTP协议即将被更改,更改后的协议就是Upgrade: websocket指定的WebSocket协议。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=
  • 以上过程称之为WebSocket协议握手(WebSocket Protocol handshake),有点类似于TCP上次握手,实际上这个WebSocket也确实是基于我们刚才发起的http的TCP连接。

  • 然后就可以通过WebSocket进行服务端和客户端之间的连接啦,其提供两种数据传输方式:文本数据和二进制数据。


WebSocket出现前,Web端的即时通讯方法:
长轮询:客户端首先给服务端发送一个请求,服务端收到该请求之后如果数据没有更新则并不立即返回,服务端阻塞请求的返回,直到数据发生了更新或者发生了连接超时,服务端返回数据之后客户端再次发送同样的请求

基于流式数据传输的长连接:通常的做法是在页面中嵌入一个隐藏的iframe,然后让这个iframe的src属性指向我们请求的一个服务端地址,并且为了数据更新,我们将页面上数据更新操作封装为一个js函数,将函数名当做参数传递到这个地址当中。
服务端收到请求后解析地址取出参数(客户端js函数调用名),每当有数据更新的时候,返回对客户端函数的调用,并且将要跟新的数据以js函数的参数填入到返回内容当中

4、WebScoket基本API

服务端:

// 导入WebSocket模块:
const WebSocket = require('ws');

// 引用Server类:
const WebSocketServer = WebSocket.Server;

// 实例化: 在3000端口上打开一个WebSocket Server
const wss = new WebSocketServer({
    port: 3000
});

//监听connection事件
wss.on('connection', function (ws) {
    console.log(`[SERVER] connection()`);
    ws.on('message', function (message) {
        console.log(`[SERVER] Received: ${message}`);
        ws.send(`ECHO: ${message}`, (err) => {
            if (err) {
                console.log(`[SERVER] error: ${err}`);
            }
        });
    })
});

客户端:

 var ws = new WebSocket("ws://localhost:3000");
 //建立连接 
 ws.onopen = function(){ws.send(“Test!”); };
 //响应收到的信息 
 ws.onmessage = function(evt){console.log(evt.data);}; 
 //关闭连接
 ws.onclose = function(evt){console.log(“WebSocketClosed!”);};
 //出错 
 ws.onerror = function(evt){console.log(“WebSocketError!”);};
 //向服务端发送信息
 ws.send('xxx');
展开阅读全文

没有更多推荐了,返回首页