简单的 C# WebSockets 服务器
Posted
技术标签:
【中文标题】简单的 C# WebSockets 服务器【英文标题】:Simple C# WebSockets Server 【发布时间】:2011-11-24 18:46:18 【问题描述】:我正在尝试使用以下内容创建一个简单的 WebSockets 服务器:
namespace ConsoleWebSocketServer
class Program
const string c_MagicKey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
static void Main(string[] args)
TcpListener l_Listener = new TcpListener(IPAddress.Loopback, 8181);
l_Listener.Start();
while (true)
using (TcpClient l_Client = l_Listener.AcceptTcpClient())
using (NetworkStream l_Stream = l_Client.GetStream())
var l_headers = new Dictionary<string, string>();
string l_line = string.Empty;
while ((l_line = ReadLine(l_Stream)) != string.Empty)
var tokens = l_line.Split(new char[] ':' , 2);
if (!string.IsNullOrWhiteSpace(l_line) && tokens.Length > 1)
l_headers[tokens[0]] = tokens[1].Trim();
string l_secKey = l_headers["Sec-WebSocket-Key"];
string l_responseSecKey = ComputeWebSocketHandshakeSecurityHash09(l_secKey);
string l_response =
"HTTP/1.1 101 Switching Protocols" + Environment.NewLine +
"Upgrade: websocket" + Environment.NewLine +
"Connection: Upgrade" + Environment.NewLine +
"Sec-WebSocket-Accept: " + l_responseSecKey + Environment.NewLine + Environment.NewLine;
var l_bufferedResponse = Encoding.UTF8.GetBytes(l_response);
l_Stream.Write(l_bufferedResponse, 0, l_bufferedResponse.Length);
public static string ComputeWebSocketHandshakeSecurityHash09(string secWebSocketKey)
string secWebSocketAccept = null; ;
string l_combinedKey = secWebSocketKey + c_MagicKey;
SHA1 l_Sha1Crypto = new SHA1CryptoServiceProvider();
byte[] l_sha1Hash = l_Sha1Crypto.ComputeHash(Encoding.UTF8.GetBytes(l_combinedKey));
secWebSocketAccept = Convert.ToBase64String(l_sha1Hash);
return secWebSocketAccept ?? String.Empty;
static string ReadLine(Stream stream)
var l_Sb = new StringBuilder();
var l_buffer = new List<byte>();
while (true)
l_buffer.Add((byte)stream.ReadByte());
string l_line = Encoding.ASCII.GetString(l_buffer.ToArray());
if (l_line.EndsWith(Environment.NewLine))
return l_line.Substring(0, l_line.Length - 2);
我正在使用执行以下操作的简单页面对其进行测试:
function testWebSocket()
if (!window.WebSocket)
alert('WebSockets are NOT supported by your browser.');
return;
var ws = new WebSocket('ws://localhost:8181/demo');
ws.onopen = function()
alert('Handshake successfully established. Ready for data...');
;
ws.onmessage = function (e)
alert('Got WebSockets message: ' + e.data);
ws.onclose = function()
alert('Connection closed.');
;
我只看到“握手”警报,紧接着是“关闭”消息。我错过了什么吗?
【问题讨论】:
仅供参考:WebSockets 将包含在 .NET 4.5 中 我没有看到您在套接字中写入除了标头之外的任何内容。 @the_ajp: If I l_Stream.Write(Encoding.UTF8.GetBytes("Test"), 0, 5) 在发送握手后,我在客户端看不到它。 一些额外的资源。 Websockets 101 dated 09/2012 和 Writing WebSocket servers from MDN 以及看到 Wikipedia websocket article 和这篇文章与 Java WebSockets – A Quick Introduction and a Sample Application 【参考方案1】:好的,在您可以向客户端发送“测试”之前,您还需要执行更多协议。开始。我使用了一个字节列表,因为它很简单:)
List<byte> lb= new List<byte>();
// see http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
// page 30 for this:
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-------+-+-------------+-------------------------------+
// |F|R|R|R| opcode|M| Payload len | Extended payload length |
// |I|S|S|S| (4) |A| (7) | (16/64) |
// |N|V|V|V| |S| | (if payload len==126/127) |
// | |1|2|3| |K| | |
// +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
// | Extended payload length continued, if payload len == 127 |
// + - - - - - - - - - - - - - - - +-------------------------------+
// | |Masking-key, if MASK set to 1 |
// +-------------------------------+-------------------------------+
// | Masking-key (continued) | Payload Data |
// +-------------------------------- - - - - - - - - - - - - - - - +
// : Payload Data continued ... :
// + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
// | Payload Data continued ... |
// +---------------------------------------------------------------+
//
//0x81 = 10000001 which says according to the table above:
// 1 it's the final message
// 000 RSV1-3 are extensions which must be negotiated first
// 0001 opcode %x1 denotes a text frame
lb.Add(0x81);
//0x04 = 00001000
// 0 No mask
// 0001000 Rest of the 7 bytes left is the length of the payload.
lb.Add(0x04);
// add the payload
lb.AddRange(Encoding.UTF8.GetBytes("Test"));
//write it!
l_Stream.Write (lb.ToArray(), 0, 6);
哇哦结果!:
【讨论】:
以上是关于简单的 C# WebSockets 服务器的主要内容,如果未能解决你的问题,请参考以下文章
WCF C# 应用程序中的 Websockets 到 ORACLE 数据库
用于 html、json 和 websockets 的自托管 Web 服务器所需的方向