2019-07-09(websocket原理,nodejs原生socket net)

WebSocket原理

1.双向
2.高效


socket.io

  • 服务端
    socket.on('connection', function(){});
    socket.on('disconnect', function(){});
  • 客户端
    socket.on('connect', function(){});
    socket.on('disconnect', function(){});

原生WebSocket

  • WebSocket 是前台的东西,是Html5自带的,后台只有Socket

握手连接数据

GET / HTTP/1.1
Host: localhost:8080
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: file://
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: io=1xmCQieVn0lSrrN-AAAA
Sec-WebSocket-Key: XOP3MFdA3K93Uo8EPd8g9Q==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

处理连接数据
1.第一行 (请求行) 删掉

GET / HTTP/1.1

2.每行数据用": "切开

let lines = str.split('\r\n');

3.舍弃第一行(请求头),最后两行(空的)

`lines = lines.slice(1, lines.length - 2);`

4.切开(所有数据转换成 key value 保存 )

let headers={};
lines.forEach((line=>{
  let [key, val] = line.split(': ');
  headers[key.toLowerCase()] = val;
  }))

5.判断服务类型, 对比socket版本, 将处理信息放到消息头里返回给客户端 (完成握手过程)

if(headers[`upgrade`] != `websocket`){
    console.log('其他协议', headers[`upgrade`]);
    //如果不是websocket 协议,直接关闭连接
    sock.end();
}
else if(headers[`sec-websocket-version`] != 13){
    console.log('版本不对', headers[`sec-websocket-version`]);
    //版本不对
    sock.end();
}
else{
    let key=headers[`sec-websocket-key`];
    let mask = `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`;
    //   sha1(key+mask) -> base64 ==> client    转换成base64的格式发送给客户端 完成协议升级
    let hash = crypto.createHash('sha1');
    hash.update(key + mask);
    let key2 = hash.digest('base64');
    // console.log(key2);
    //101状态码   switching protocols  切换协议类型, 协议升级
    sock.write(`Http/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ${key2}\r\n\r\n`); //\r\n http协议标准分行,所以要加
    //连接成功  就不需要断开了
    // sock.end();      
    //握手结束
    console.log('hand shake end...');
    //真正的数据
    sock.on('data', data=>{
        console.log('有数据了');
      //data 获取到的是一个数据帧
    })
}

  • 数据帧


    image
1.FIN                   是否最后一帧(1 bit)
2.RSV1、RSV2、RSV3      预留位
3.opcode                帧类型
4.MASK                  掩码,是否加密数据,默认必须置为 1(WebSocket设计必须是加密的所以这里一定为1)
5.Payload len           数据长度(内容的长度,单位字节)
6.Extended Payload length    扩展的内容长度

使用WebSocket

  • socket.io库
  • 原生WebWocket
    1.net模块
    2.流程
    3.握手
---  C:version:13、sec-websocket-key:xxxxxx、
---  S:101 Swiching Protocols 切换协议、sec-websocket-accept :base64 (sha1(mask+sec-websocket-key)=>base64 返还给客户端)
---  握手完成,客户端服务器双向通讯
事件:
  Client:
      onopen
      onmessage
      onclose
  Server:
      sock.once('data', 握手)
          sock.on('data', 其他数据请求)
      sock.on('end', 连接断开)

4.数据帧解析(解包)

你可能感兴趣的:(2019-07-09(websocket原理,nodejs原生socket net))