一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
什么是socket?
socket倒不是什么协议,在网络中其实是一个抽象层。任何一个计算机语言要进行网络通信的话基本上都是通过socket抽象层进行通信。它是基于TCP/IP协议的。
- 客户端链接服务器,三次握手建立连接通道。
- 客户端和服务端通过socket接口发送和接收消息。任何一端在任何时候都可以向另一端发送任何消息。
- 有一端断开,通道销毁。
HTTP
HTTP是建立在socket之上的。
- 客户端连接服务器,三次握手,建立连接通道。
- 客户端发送一个http格式消息(消息头、消息体),服务器响应http格式消息。
- 客户端或服务器断开,通道销毁。
http的问题在于,如果我们对某一要求实时性要求非常高,每一次交互都是客户端发起的,而消息的变动在服务器但是无法主动发送给客户端。
遇到这种问题,一般有以下解决方法:
- 轮询: 会造成很多无用的请求,增加内存开销。
- 长连接(keep-alive):服务器不会主动断开,如果服务器不给响应,浏览器就会一直等待,等消息变了才发送。
websocket
在HTML5出现之后,推出浏览器支持的websocket协议也推出基于websocket的web API。
websocket专门用来解决时事消息的事情。
- 客户端连接服务器,三次握手,建立连接通道。
- 客户端发送一个http格式的消息(特殊格式),服务器也响应一个http格式的消息(特殊格式),称为http握手。(确认是否支持socket)
- 双方自由通信,通信格式按照websocket的要求进行
- 客户端或服务器断开,通道销毁。
// 客户端 创建websocket
// 发送连接到服务器
const ws = new WebSocket("ws://localhost:8080");
//当连接建立运行的事件
ws.onopen = function() {
console.log('连接建立');
}
// 接收数据的事件
ws.onmessage = function(e){
console.log('来自服务器的数据', e.data);
}
// 发送数据到服务器
ws.send('123');
// 客户端主动断开
ws.close();
// 任何一方断开连接运行的事件
ws.onclose = function() {
console.log('通道关闭')
}
// 服务端 用net模块创建服务
const net = require('net');
const server = net.createServer((socket)=>{
console.log('收到客户端的连接');
// 向浏览器发送确认信息
socket.once('data', chunk => {
const httpContent = chunk.toString('utf-8');
let parts = httpContent.split('\r\n');
parts.shift();
parts = parts.filter(s=>s).map(s=>{
const i = s.indexof(":");
return [s.substr(0,i), s.substr(i+1).trim()];
})
const headers = Object.formEntries(parts);
const crypto = require('crypto');
const hash = crypto.createHash('sha1');
hash.update(
headers['Sec-WebSocket-Key'] + "258EAFA5-E914-47DA-95CA-C5AB0DC85V11"
);
cibst key = hash.digest('base64');
socket.write(`HTTP/1.1 101 Switching Protocols
Upgrade:websocket
Connection:Upgrade
sec-WebSocket-Accept:${key}
`);
})
});
server.listen(8080)