摘要:WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。WebSocket通信协议于2011年被IETF定为标准RFC6455,并被RFC7936所补充规范。
简单的说,Websocket协议之前,双工通信是通过多个HTTP链接来实现,这导致了效率低下(轮询)。另外就是,一般浏览器和tomcat通信十分方便,那么当一个电脑上没有服务器框架的时候,该如何与浏览器通信呢?只能建立socket进行通信。而浏览器是不能建立普通socket的,只有最近几年开始才有了一种叫做Websocket的协议。
长久以来,创建实现客户端和用户端之间双工通讯的Web App都会造成HTTP轮询的滥用:客户端向主机不断发送不同的HTTP呼叫来进行询问。
这会导致一系列的问题:
- 服务器被迫为每个客户端使用许多不同的底层TCP连接:一个用于向客户端发送信息,其它用于接收每个传入消息。
- 有线协议有很高的开销,每一个客户端和服务器之间都有HTTP头。
- 客户端脚本被迫维护从传出连接到传入连接的映射来追踪回复。
一个更简单的解决方案是使用单个TCP连接双向通信。 这就是Websocket协议所提供的功能。 结合Websocket API ,Websocket协议提供了一个用来替代HTTP轮询实现网页到远程主机的双向通信的方法。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=
WebSocket借用HTTP请求进行握手,相比正常的HTTP请求,多了一些内容。 浏览器请求,一般不太需要关心,这里主要讲一下服务器如何回应Websocket请求。
Sec-WebSocket-Accept
是将请求包Sec-WebSocket-Key
的值,与258EAFA5-E914-47DA-95CA-C5AB0DC85B11
这个字符串进行拼接,然后对拼接后的字符串进行sha-1
运算,再进行base64
编码得到的。
首先是与浏览器完成握手,一些具体的信息可以参见《WebSocket》一文。
/// <summary>
/// 打包握手信息
/// </summary>
/// <param name="secKeyAccept"></param>
/// <returns></returns>
private static byte[] packHandShakeData(string secKeyAccept)
{
Console.WriteLine("Package hand shake.");
var responseBuilder = new StringBuilder();
responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);
return Encoding.UTF8.GetBytes(responseBuilder.ToString());
}
/// <summary>
/// 生成Sec-WebSocket-Accept
/// </summary>