(1)什么是WebSocket
WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。
在WebSocket API中,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
优点:
a、服务器与客户端之间交换的标头信息很小,大概只有2字节
b、服务器可以主动传送数据给客户端
(2)WebSocket(13)握手
WebSocket握手由客户端发起,报文样例:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
这里Sec-WebSocket-Version表明版本号是13;注意Sec-WebSocket-Key,这是客户端发送的密钥,服务端需要对该密钥进行处理,反馈给客户端,客户端验证密钥正确后就开始通信,这之后该密钥就没用了。
服务端反馈样例:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
C#服务端首先提取Sec-WebSocket-Key的字符串,加上“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”(是一个固定的GUID),用SHA1计算哈希码,用base64加密,最终生成Sec-WebSocket-Accept的内容。握手代码:
private void handShake(byte[] recBytes, int recByteLength)
{
string recStr = Encoding.UTF8.GetString(recBytes, 0, recByteLength);
string[] ss = recStr.Split(Environment.NewLine.ToCharArray());
string key = ss[10].Replace("Sec-WebSocket-Key: ", "");
key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
SHA1 sha1 = SHA1.Create();
byte[] sha1bytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(key));
string acceptStr = Convert.ToBase64String(sha1bytes);
string sendStr = "HTTP/1.1 101 Switching Protocols" + NewLine +
"Upgrade: websocket" + NewLine +
"Connection: Upgrade" + NewLine +
"Sec-WebSocket-Accept: " + acceptStr + NewLine +
"Sec-WebSocket-Protocol: chat" + NewLine + NewLine;
client.Send(System.Text.Encoding.UTF8.GetBytes(sendStr));
isHandshaked = true;
}
(3)接收客户端数据
客户端调用send方法将字符窜发送到服务端。服务端要以二进制(bit)解析frame的前两个byte,过程如下:
1byte
1bit: frame-fin,x0表示该message后续还有frame;x1表示是message的最后一个frame
3bit: 分别是frame-rsv1、frame-rsv2和frame-rsv3,通常都是x0
4bit: frame-opcode,x0表示是延续frame;x1表示文本frame;x2表示二进制frame;x3-7保留给非控制frame;x8表示关闭连接;x9表示ping;xA表示pong;xB-F保留给控制frame
2byte
1bit: Mask,1表示该frame包含掩码;0,表示无掩码
7bit、7bit+2byte、7bit+8byte: 7bit取整数值,若在0-125之间,则是负载数据长度;若是126表示,后两个byte取无符号16位整数值,是负载长度;127表示后8个byte,取64位无符号整数值,是负载长度
3-6byte: 这里假定负载长度在0-125之间,并且Mask为1,则这4个byte是掩码
7-end byte: 长度是上面取出的负载长度,包括扩展数据和应用数据两部分,通常没有扩展数据;若Mask为1,则此数据需要解码,解码规则为1-4byte掩码循环和数据byte做异或操作。
C#接收数据代码如下:
private bool recData(byte[] recBytes, int recByteLength)
{
if (recByteLength < 2)
return false;
bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧
if (!fin)
{
Console.WriteLine("recData exception: 超过一帧"); // 超过一帧暂不处理
return false;
}
bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码
if (!mask_flag)
{
Console.WriteLine("recData exception: 没有Mask"); // 不包含掩码的暂不处理
return false;
}
int payload_len = recBytes[1] & 0x7F; // 数据长度
byte[] masks = new byte[4];
byte[] payload_data;
if (payload_len == 126)
{
Array.Copy(recBytes, 4, masks, 0, 4);
payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
payload_data = new byte[payload_len];
Array.Copy(recBytes, 8, payload_data, 0, payload_len);
}
else if (payload_len == 127)
{
Array.Copy(recBytes, 10, masks, 0, 4);
byte[] uInt64Bytes = new byte[8];
for (int i = 0; i < 8; i++)
{
uInt64Bytes[i] = recBytes[9 - i];
}
UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);
payload_data = new byte[len];
for (UInt64 i = 0; i < len; i++)
payload_data[i] = recBytes[i + 14];
}
else
{
Array.Copy(recBytes, 2, masks, 0, 4);
payload_data = new byte[payload_len];
Array.Copy(recBytes, 6, payload_data, 0, payload_len);
}
for (var i = 0; i < payload_len; i++)
payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
string content = Encoding.UTF8.GetString(payload_data);
Console.WriteLine("client: {0}", content);
return true;
}
(3)发送数据到客户端
服务器发送的数据以0x81开头,紧接发送内容的长度(若长度在0-125,则1个byte表示长度;若长度不超过0xFFFF,则后2个byte作为无符号16位整数表示长度;若超过0xFFFF,则后8个byte作为无符号64位整数表示长度),最后是内容的byte数组。
C#发送代码:
private void sendData(string content)
{
byte[] contentBytes = null;
byte[] temp = Encoding.UTF8.GetBytes(content);
if (temp.Length < 126)
{
contentBytes = new byte[temp.Length + 2];
contentBytes[0] = 0x81;
contentBytes[1] = (byte)temp.Length;
Array.Copy(temp, 0, contentBytes, 2, temp.Length);
}
else if (temp.Length < 0xFFFF)
{
contentBytes = new byte[temp.Length + 4];
contentBytes[0] = 0x81;
contentBytes[1] = 126;
contentBytes[2] = (byte)(temp.Length & 0xFF);
contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);
Array.Copy(temp, 0, contentBytes, 4, temp.Length);
}
else
{
// 暂不处理超长内容
}
client.Send(contentBytes);
}
(4)html客户端代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebSocket</title>
<script type="text/javascript">
if (!window.WebSocket)
alert("WebSocket not supported by this browser!");
var ws;
function connectWS() {
if (ws == null) {
ws = new WebSocket("ws://127.0.0.1:5001");
ws.onmessage = function (evt) {
alert("接收到信息:" + evt.data);
};
ws.onclose = function () {
alert("连接已关闭。");
ws = null;
};
ws.onerror = function (evt) {
alert("连接出错:" + evt.data);
ws = null;
}
ws.onopen = function (evt) {
alert("连接已打开。");
};
}
}
function sendWS() {
if (ws != null) {
try {
var sendstr = document.getElementById("txtSend").value;
if (sendstr == "")
return;
ws.send(sendstr);
} catch (err) {
alert(err.Data);
}
} else {
alert("连接失效。");
}
}
function closeWS() {
ws.send("exit");
ws.close();
}
</script>
</head>
<body style="text-align: center;">
<input type="button" value="连接" onclick="connectWS()" />
<input type="button" value="断开" onclick="closeWS()" />
<br />
<input type="text" id="txtSend" /><input type="button" id="btnSend" value="发送" onclick="sendWS()" />
</body>
</html>
附件是服务端代码,以及html测试网页
以上
分享到:
相关推荐
C#实现WebSocket源码(c#写的服务端html写的客户端) WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。 它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器...
WebSocket协议作为一种在单个TCP连接上进行全双工通信的技术,使得客户端和服务器之间能够进行低延迟、高效率的数据交换,非常适合于实时推送通知、在线聊天、游戏实时更新等场景。使用C# WinForm结合WebSocket...
本项目包含了一个完整的C#版Socket通信示例,涵盖了服务端、客户端以及WebSocket的实现,对于学习和理解网络通信机制具有很高的参考价值。 首先,我们来详细探讨Socket的基本概念。Socket是网络通信的一种接口,它...
WebSocket是一种在客户端和服务器之间建立长连接的协议,它提供了双向通信的能力,即服务器和客户端都可以主动发送数据。在Web开发中,WebSocket替代了传统的HTTP请求-响应模式,极大地提高了实时性,尤其适用于需要...
WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许双方进行双向通信,极大地提高了实时性。在IT行业中,尤其是在开发实时应用如聊天室、在线游戏或者股票交易系统时,WebSocket已经成为首选的通信技术...
在C#中开发WebSocket服务端和客户端,可以实现双向通信,即服务器和客户端都能主动发送数据,这对于实时性要求高的应用,如在线聊天、游戏、股票交易等场景非常适用。 WebSocketSharp是C#中的一个开源库,它为C#...
c# winform快速建websocket服务器源码 wpf快速搭建websocket服务 c#简单建立websocket服务 websocket快速搭建 ...本文将探讨WebSocket通信技术的优势,并阐述为何选择C#作为服务端开发语言的几大理由。
WebSocket 是一种在客户端和服务器之间建立持久连接的协议,它允许双向通信,即服务器和客户端都可以主动发送数据。在C# MVC(Model-View-Controller)框架中集成WebSocket,可以创建实时、低延迟的在线聊天应用。...
总结来说,WebSocket Sharp 提供了一个强大且灵活的工具,用于在C#环境中实现WebSocket协议,无论是构建实时交互的Web应用,还是在Unity游戏开发中实现网络通信,都是一个值得考虑的选择。通过理解和掌握其基本用法...
总的来说,WebSocketDemo(C#)是一个学习和实践WebSocket协议以及SuperSocket框架的好例子。它展示了如何利用这些技术实现实时双向通信,这对于开发聊天应用、在线游戏、股票交易系统等需要实时数据交换的场景非常...
本实例是一个基于C#的WebSocket应用,包括服务端和客户端的源代码,适用于Visual Studio 2017开发环境。 首先,我们来看服务端部分。服务端通常是WebSocket通信的起点,它监听特定的端口,等待客户端的连接请求。在...
总结,通过结合C# WinForm的强大UI功能和WebSocket的实时通信能力,我们可以创建出高效的桌面应用。在VS2019中,利用WebSocket4Net库,我们可以轻松地实现客户端与WebSocket服务器之间的数据交换,从而满足各种实时...
WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许双方进行双向通信,极大地提高了实时性。在IT行业中,尤其是在开发实时应用如在线聊天、股票交易、多人在线游戏等场景时,WebSocket已经成为首选的...
WebSocket是Web应用中实现双向通信的一种技术,它允许服务器和客户端之间进行实时、低延迟的数据交换。在C#中,可以使用.NET Framework或.NET Core来实现WebSocket客户端和服务端的开发。下面将详细介绍C# WebSocket...
WebSocket是Web通信协议的一种,它允许在客户端和服务器之间建立持久的、低延迟的双向连接。在C#和ASP.NET MVC框架下,WebSocket提供了一种高效的方式来进行实时数据交互,尤其适用于在线聊天、游戏、股票交易等需要...
总的来说,结合C# WinForm的用户交互能力和WebSocket的实时通信特性,可以构建出一个高效且用户友好的文件传输系统。在实际项目中,可能还需要考虑安全性问题,如数据加密、身份验证等,以保证文件传输的安全。这个...
WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许双方进行全双工通信,即数据可以在两个方向上同时传输,极大地提高了实时性。在C#中,WebSocket的使用主要依赖于.NET Framework或.NET Core提供的...
WebSocketSharp 是一个 C# 实现的 WebSocket 客户端和服务器框架,它为开发者提供了在 .NET 应用程序中实现 WebSocket 协议的强大工具。WebSocketSharp 允许你轻松地创建可以双向通信的实时应用,例如在线游戏、实时...
总的来说,这个"WebSocket C#/ASP.NET 示例"提供了一个实用的学习资源,演示了如何在ASP.NET MVC中集成WebSocket,利用C#和SuperWebSocket实现服务器与客户端之间的实时通信。对于想要提升Web应用实时性特性的开发者...