We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
名字: web + socket
可以将服务端主机想象成一个布满各种插座的房间,每个插座有一个编号,有的插座提供 220 伏交流电,有的提供固定电话信号,有的则提供有线电视节目。客户端软件将插头接入不同编号的插座,就可以得到不同的服务
Socket 其实并不是一个标准的协议,而是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,工作位置基本在 OSI 模型会话层(第5层),是为了方便大家直接使用更底层协议(一般是 TCP 或 UDP )而存在的一个抽象层。
为 C/S 两端提供了实时交互通信的能力,允许服务器主动发送信息给客户端,是一种区别于 HTTP 的全新双向数据流协议
传统的 TCP Socket 是一套相对标准化的 API,而出现时间不久的 WebSocket 是一种网络协议
在基于 请求/响应 模式的 HTTP/HTTPS 下,如果是对实时性要求较高的场景,客户端就需要不停的询问服务端有无可用的数据,这在各方面都是笨拙而不划算的。
早起解决方式:
借助于定时器等方式,客户端不断的发送请求并得到响应。这种做法比较简单,可以在一定程度上解决问题。不过对于轮询的时间间隔需要进行仔细考虑。轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担。
this.timerCount = setInterval(() => this.xxxxx(), time); clearInterval(this.timerCount);
这是对轮询的一种改进。客户端发出请求后,服务器端用 while(true) 等方式阻塞住请求,直到有可用数据才发送响应数据或者超时,而客户端收到响应后再发送下一个请求。
function async() { fetch(url).then((res) => { async(); // success code }).catch(() => { // 超时 async(); }) }
使用 HTTP 1.1 且响应头中包含 Transfer-Encoding: chunked 的情况下,服务器发送给客户端的数据可以分成多个部分,保持打开(while-true, sleep等),并周期性 flush() 分块传输。
Transfer-Encoding: chunked
客户端只发送一个HTTP连接,在 xhr.readyState==3 状态下,用 xhr.responseText.substring 获取每次的数据。
但是数据响应可能会因 代理服务器 或 防火墙 等中间人造成延迟,所以可能还要额外探测这种情况以切换到长轮询方式。
缺点:
浪费带宽
CPU占用高
websocket 参考
实现双向通讯
当客户端要和服务端建立 WebSocket 连接时,在客户端和服务器的握手过程中,客户端首先会向服务端发送一个 HTTP 请求,包含一个 Upgrade 请求头来告知服务端客户端想要建立一个 WebSocket 连接。
WebSocket是基于TCP的独立的协议。 和HTTP的唯一关联就是HTTP服务器需要发送一个“Upgrade”请求,即101 Switching Protocol到HTTP服务器,然后由服务器进行协议转换。
101 Switching Protocol
客户端使用非常简单,服务端难。。。
2.1.1 front侧使用
// front 比较简单 const ws = new WebSocket('wss://xxxx.com/xxxx'); // 与webSocket服务连接 ws.onmessage = function(evt) { console.log("Received Message: " + evt.data); ws.close(); }; ws.onclose = function(evt) { console.log("Connection closed."); };
2.1.2 服务端(node)
客户端通过 HTTP Upgrade 请求,即 101 Switching Protocol 到 HTTP 服务器,然后由服务器进行协议转换。
const http = require('http'); const WebSocket = require('./websocket'); // HTTP服务器部分 const server = http.createServer(function(req, res) { res.end('websocket test'); }); console.log('starting...'); // Upgrade请求处理 server.on('upgrade', callback); function callback(req, socket, upgradeHead) { const ws = new WebSocket(req, socket, upgradeHead); ws.on('data', function(opcode, payload) { console.log('receive data:', opcode, payload.length); }); ws.on('close', function(code, reason) { console.log('close:', code, reason); }); } server.listen(3000);
webSocket实现
接收前台数据并处理:
const crypto = require('crypto'); const { EventEmitter } = require('events'); const MAGIC_STRING = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; const hashWebSocketKey = (key) => { const sha1 = crypto.createHash('sha1'); sha1.update(key + MAGIC_STRING, 'ascii'); return sha1.digest('base64'); }; // 继承node内置的EventEmitter ,这样生成的实例才能监听、绑定事件 class WebSocket extends EventEmitter { constructor(req, socket, upgradeHead) { super(); const resKey = hashWebSocketKey(req.headers['sec-websocket-key']); // 根据协议规范构造响应头 const resHeaders = [ 'HTTP/1.1 101 Switching Protocols', 'Upgrade: websocket', 'Connection: Upgrade', 'Sec-WebSocket-Accept: ' + resKey ] .concat('', '') .join('\r\n'); // socket 就是 TCP 协议的抽象,直接在上面监听已有的 data 事件和 close 事件这两个事件。 socket.on('data', data => { // 通信数据处理 //.... this.emit('data', data) // 以供服务端监听处理后的数据 }); socket.on('close', had_error => { // }); socket.write(resHeaders); this.socket = socket; } } module.exports = WebSocket;
帧顺序
报文的顺序是由TCP来保证的,所以要求消息的分片必须由发送者按给定的顺序发送给接收者,以此让 TCP给报文打上正确的编号。
消息的分片必须由发送者按给定的顺序发送给接收者
向前台发送数据(和接收正好相反):
The text was updated successfully, but these errors were encountered:
No branches or pull requests
WebSocket
1. 详解
名字: web + socket
1.1 socket(插座,套接字)
可以将服务端主机想象成一个布满各种插座的房间,每个插座有一个编号,有的插座提供 220 伏交流电,有的提供固定电话信号,有的则提供有线电视节目。客户端软件将插头接入不同编号的插座,就可以得到不同的服务
Socket 其实并不是一个标准的协议,而是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,工作位置基本在 OSI 模型会话层(第5层),是为了方便大家直接使用更底层协议(一般是 TCP 或 UDP )而存在的一个抽象层。
1.2 webSocket
为 C/S 两端提供了实时交互通信的能力,允许服务器主动发送信息给客户端,是一种区别于 HTTP 的全新双向数据流协议
传统的 TCP Socket 是一套相对标准化的 API,而出现时间不久的 WebSocket 是一种网络协议
1.2.1 解决的问题
在基于 请求/响应 模式的 HTTP/HTTPS 下,如果是对实时性要求较高的场景,客户端就需要不停的询问服务端有无可用的数据,这在各方面都是笨拙而不划算的。
早起解决方式:
借助于定时器等方式,客户端不断的发送请求并得到响应。这种做法比较简单,可以在一定程度上解决问题。不过对于轮询的时间间隔需要进行仔细考虑。轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担。
这是对轮询的一种改进。客户端发出请求后,服务器端用 while(true) 等方式阻塞住请求,直到有可用数据才发送响应数据或者超时,而客户端收到响应后再发送下一个请求。
使用 HTTP 1.1 且响应头中包含
Transfer-Encoding: chunked
的情况下,服务器发送给客户端的数据可以分成多个部分,保持打开(while-true, sleep等),并周期性 flush() 分块传输。客户端只发送一个HTTP连接,在 xhr.readyState==3 状态下,用 xhr.responseText.substring 获取每次的数据。
但是数据响应可能会因 代理服务器 或 防火墙 等中间人造成延迟,所以可能还要额外探测这种情况以切换到长轮询方式。
缺点:
浪费带宽
CPU占用高
1.2.2 webSocket
websocket 参考
实现双向通讯
当客户端要和服务端建立 WebSocket 连接时,在客户端和服务器的握手过程中,客户端首先会向服务端发送一个 HTTP 请求,包含一个 Upgrade 请求头来告知服务端客户端想要建立一个 WebSocket 连接。
WebSocket是基于TCP的独立的协议。
和HTTP的唯一关联就是HTTP服务器需要发送一个“Upgrade”请求,即
101 Switching Protocol
到HTTP服务器,然后由服务器进行协议转换。2. 使用和实现
客户端使用非常简单,服务端难。。。
2.1 WebSocket API
2.1.1 front侧使用
2.1.2 服务端(node)
客户端通过 HTTP Upgrade 请求,即 101 Switching Protocol 到 HTTP 服务器,然后由服务器进行协议转换。
webSocket实现
接收前台数据并处理:
帧顺序
报文的顺序是由TCP来保证的,所以要求
消息的分片必须由发送者按给定的顺序发送给接收者
,以此让 TCP给报文打上正确的编号。向前台发送数据(和接收正好相反):
The text was updated successfully, but these errors were encountered: