C#HTML5 Websocket服务器

我正在尝试创建一个C#Websocket服务器,但我似乎并没有让它工作。 我现在有一个接受TCPClient的服务器,从客户端接收HTTP请求并尝试发回HTTP响应,以便完成HTML5 WebSocket握手。

我相信服务器发送给客户端的握手有问题。 我阅读了草案( Websocket 76草案 ),其中指出在握手结束时必须给出给出的两个键的响应。 此响应由服务器计算。

这是我的代码:

static void Main(string[] args) { int port = 8181; IPAddress localAddr = IPAddress.Loopback; TcpListener server = new TcpListener(localAddr, port); server.Start(); // Buffer for reading data Byte[] receivedBytes = new Byte[256]; String data = null; // Enter the listening loop. while (true) { Console.WriteLine("Waiting for a connection..."); // Perform a blocking call to accept requests. // You could also user server.AcceptSocket() here. TcpClient client = server.AcceptTcpClient(); Console.WriteLine("Connected!\n"); data = null; // Get a stream object for reading and writing NetworkStream stream = client.GetStream(); int i; // Loop to receive all the data sent by the client. while ((i = stream.Read(receivedBytes, 0, receivedBytes.Length)) != 0) { // Translate data bytes to a ASCII string. data = System.Text.Encoding.UTF8.GetString(receivedBytes, 0, i); Console.WriteLine("Received:"); Console.WriteLine(data); Byte[] response_token = hashResponse(data); string handshake = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" + "Upgrade: WebSocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Origin: http://localhost\r\n" + "Sec-WebSocket-Location: ws://localhost:8181/websession\r\n" + "\r\n"; Byte[] writtenBytes = Encoding.UTF8.GetBytes(handshake); stream.Write(writtenBytes, 0, writtenBytes.Length); stream.Write(response_token, 0, response_token.Length); Console.WriteLine("Send:"); Console.WriteLine(handshake); string strHash = Encoding.UTF8.GetString(response_token); Console.WriteLine(strHash); } } } static Byte[] hashResponse(string receivedData) { string strDel = "\r\n"; char[] delimeter = strDel.ToCharArray(); string Key1 = null; string Key2 = null; string hash = null; MD5 md5 = MD5.Create(); string[] lines = receivedData.Split(delimeter); Key1 = lines[10].Substring(20); Key2 = lines[12].Substring(20); hash = lines[16]; Int64 numbersKey1 = Convert.ToInt64(string.Join(null, Regex.Split(Key1, "[^\\d]"))); Int64 numbersKey2 = Convert.ToInt64(string.Join(null, Regex.Split(Key2, "[^\\d]"))); Int64 numberSpaces1 = countSpaces(Key1); Int64 numberSpaces2 = countSpaces(Key2); int dividedKey1 = (int) (numbersKey1 / numberSpaces1); int dividedKey2 = (int) (numbersKey2 / numberSpaces2); Byte[] encodedKey1 = Encoding.UTF8.GetBytes(dividedKey1.ToString()); Byte[] encodedKey2 = Encoding.UTF8.GetBytes(dividedKey2.ToString()); Byte[] encodedHash = Encoding.UTF8.GetBytes(hash); Byte[] combined = Encoding.UTF8.GetBytes(dividedKey1.ToString() + dividedKey2.ToString() + hash); Byte[] responseHash = md5.ComputeHash(combined); return responseHash; } static int countSpaces(string key) { int counter = 0; char[] charArray = key.ToCharArray(); foreach (char c in charArray) { if (c.Equals(' ')) counter++; } return counter; } 

我用于测试的HTML页面(名为Test.html)由我的计算机上运行的apache webserver托管,我通过浏览(在Chrome中)访问http://localhost/Test.html来访问它

有没有人知道我做错了什么因为我变得非常绝望。

提前致谢

丹尼斯

这是我编写的示例服务器,根据draft-ietf-hybi-thewebsocketprotocol-00说明握手阶段:

 using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { var listener = new TcpListener(IPAddress.Loopback, 8080); listener.Start(); while (true) { using (var client = listener.AcceptTcpClient()) using (var stream = client.GetStream()) { var headers = new Dictionary(); string line = string.Empty; while ((line = ReadLine(stream)) != string.Empty) { var tokens = line.Split(new char[] { ':' }, 2); if (!string.IsNullOrWhiteSpace(line) && tokens.Length > 1) { headers[tokens[0]] = tokens[1].Trim(); } } var key = new byte[8]; stream.Read(key, 0, key.Length); var key1 = headers["Sec-WebSocket-Key1"]; var key2 = headers["Sec-WebSocket-Key2"]; var numbersKey1 = Convert.ToInt64(string.Join(null, Regex.Split(key1, "[^\\d]"))); var numbersKey2 = Convert.ToInt64(string.Join(null, Regex.Split(key2, "[^\\d]"))); var numberSpaces1 = CountSpaces(key1); var numberSpaces2 = CountSpaces(key2); var part1 = (int)(numbersKey1 / numberSpaces1); var part2 = (int)(numbersKey2 / numberSpaces2); var result = new List(); result.AddRange(GetBigEndianBytes(part1)); result.AddRange(GetBigEndianBytes(part2)); result.AddRange(key); var response = "HTTP/1.1 101 WebSocket Protocol Handshake" + Environment.NewLine + "Upgrade: WebSocket" + Environment.NewLine + "Connection: Upgrade" + Environment.NewLine + "Sec-WebSocket-Origin: " + headers["Origin"] + Environment.NewLine + "Sec-WebSocket-Location: ws://localhost:8080/websession" + Environment.NewLine + Environment.NewLine; var bufferedResponse = Encoding.UTF8.GetBytes(response); stream.Write(bufferedResponse, 0, bufferedResponse.Length); using (var md5 = MD5.Create()) { var handshake = md5.ComputeHash(result.ToArray()); stream.Write(handshake, 0, handshake.Length); } } } } static int CountSpaces(string key) { return key.Length - key.Replace(" ", string.Empty).Length; } static string ReadLine(Stream stream) { var sb = new StringBuilder(); var buffer = new List(); while (true) { buffer.Add((byte)stream.ReadByte()); var line = Encoding.ASCII.GetString(buffer.ToArray()); if (line.EndsWith(Environment.NewLine)) { return line.Substring(0, line.Length - 2); } } } static byte[] GetBigEndianBytes(int value) { var bytes = 4; var buffer = new byte[bytes]; int num = bytes - 1; for (int i = 0; i < bytes; i++) { buffer[num - i] = (byte)(value & 0xffL); value = value >> 8; } return buffer; } } 

和客户样本:

         

不知道你是否可以编译Objective C,但是这个项目非常酷 ……

Blackbox是一个可嵌入的Cocoa HTTP服务器 – 它允许您将HTTP资源与Cocoa“响应者”对象(类似于Twisted Web对Python的对象)关联,而不是文件系统上的文件。

使用Blackbox,您可以快速创建个人文件共享器,编写通过HTTP相互通信的应用程序,并轻松为无头应用程序创建Web控制界面。

它基本上是一个很好的包中的Comet服务器 。 我希望我可以多说一些,但我仍然在试图找出自己的sockets……

请注意,“彗星演示”窗口是我的一个混合物,所以当你运行演示时,不要沮丧,只需打开你的浏览器!

尝试在尝试接收套接字上的数据之前发送握手数据

这是一个可能对您有所帮助的示例

websocksample