我的代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Net; using System.Net.Sockets; using System.Threading; using System.Security.Cryptography; using System.IO; namespace ConsoleService { class Program { static AutoResetEvent allDone = new AutoResetEvent(false); static void Main(string[] args) { IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("10.9.16.31"), 1818); Console.WriteLine("Local address and port : {0}", localEP.ToString()); Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { listener.Bind(localEP); listener.Listen(500); while (true) { Socket sc = listener.Accept(); if (sc != null) { StateObject state = new StateObject(); state.workSocket = sc; Console.WriteLine("Waiting for a connection..."); sc.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); allDone.WaitOne(); } } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("Closing the listener..."); } static void ReceiveCallback(IAsyncResult ar) { try { // Retrieve the state object and the client socket // from the asynchronous state object. StateObject state = (StateObject)ar.AsyncState; Socket client = state.workSocket; Console.WriteLine("接收自:"+state.workSocket.RemoteEndPoint.ToString()); // Read data from the remote device. int bytesRead = client.EndReceive(ar); allDone.Set(); if (bytesRead > 0) { System.Text.UTF8Encoding decoder = new System.Text.UTF8Encoding(); string browser=decoder.GetString(state.buffer,0,bytesRead); Console.WriteLine(browser); string key = string.Empty; Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n"); //查找"Abc" Match m = r.Match(browser); //设定要查找的字符串 if (m.Groups.Count != 0) { key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$1").Trim(); } Console.WriteLine("获取的客户端的KEY:"+key); string secKeyAccept = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))); Console.WriteLine("服务器端生成的KEY:"+secKeyAccept); 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); responseBuilder.Append("Sec-WebSocket-Protocol: chat" + Environment.NewLine); Console.WriteLine("服务器端欲发送信息:\r\n"+responseBuilder.ToString()); byte[] HandshakeText = Encoding.UTF8.GetBytes(responseBuilder.ToString()); state.workSocket.BeginSend(HandshakeText, 0, HandshakeText.Length, 0, new AsyncCallback(SendCallback), state); } } catch (Exception e) { Console.WriteLine(e.ToString()); } } static void SendCallback(IAsyncResult ar) { StateObject state = (StateObject)ar.AsyncState; Socket client = state.workSocket; client.EndSend(ar); Console.WriteLine("发送至:" + state.workSocket.RemoteEndPoint.ToString()+" 结束。"); Console.WriteLine("本应该握手成功的?!"); //byte[] msg = Encoding.UTF8.GetBytes("hello"); //state.workSocket.Send(msg); } } public class StateObject { public Socket workSocket = null; public const int BufferSize = 1024; public byte[] buffer = new byte[BufferSize]; public StringBuilder sb = new StringBuilder(); } }
HTML代码:
<html> <head> <meta charset="UTF-8"> <title>Web sockets test</title> <script src="jquery-min.js" type="text/javascript"></script> <script type="text/javascript"> var ws; function ToggleConnectionClicked() { try { ws = new WebSocket("ws://10.9.16.31:1818/chat"); ws.onopen = function(event){alert("连接已经建立:"+this.readyState);}; ws.onmessage = function(event){alert("接收到的数据:"+event.data);}; ws.onclose = function(event){alert("断开,信息:"+this.readyState);}; ws.onerror = function(event){alert("错误"+event.message);}; } catch (ex) { alert(ex.message); } //document.getElementById("ToggleConnection").innerHTML = "断开"; }; function SendData() { try{ ws.send("hello"); }catch(ex){ alert(ex.message); } }; function close() { try{ ws.close(); ws=null; }catch(ex){ alert(ex.message); } }; function seestate(){ alert(ws.readyState); } </script> </head> <body> <button id='ToggleConnection' type="button" onclick='ToggleConnectionClicked();'>连接</button><br /> <button id='ToggleConnection' type="button" onclick='SendData();'>发送</button><br /> <button id='ToggleConnection' type="button" onclick='close();'>断开</button><br /> <button id='ToggleConnection' type="button" onclick='seestate();'>状态</button><br /> </body> </html>
使用的浏览器版本:Google Chrome 21.0.1180.83m
但一直都没握手成功,发送了连接浏览器没任何反应,但管理服务器端确能触发onclose事件。
求解惑?
最后缺一个换行!
不行的。最后是去掉最后一行,再加上一个换行才行。
@osEye:
两个问题
1) Handshake结尾应该两个换行
2) 要传回和请求相匹配的protocol
responseBuilder.Append("Sec-WebSocket-Protocol: chat" + Environment.NewLine + Environment.NewLine);
http://www.blue-zero.com/WebSocket/ 在线WebSocket测试,客户端完美兼容IE6及以上浏览器,服务端采用【C#.NET】异步socket开发,支持多客户同时在线。
你注释掉的这两句: //byte[] msg = Encoding.UTF8.GetBytes("hello");
//state.workSocket.Send(msg);
改成下面的:
byte[] msg = PackageServerData("hello from server");
state.workSocket.Send(msg);
private static byte[] PackageServerData(string msg)
{
byte[] content = null;
byte[] temp = Encoding.UTF8.GetBytes(msg);
if (temp.Length < 126)
{
content = new byte[temp.Length + 2];
content[0] = 0x81;
content[1] = (byte)temp.Length;
Buffer.BlockCopy(temp, 0, content, 2, temp.Length);
}
else if (temp.Length < 0xFFFF)
{
content = new byte[temp.Length + 4];
content[0] = 0x81;
content[1] = 126;
content[2] = (byte)(temp.Length & 0xFF);
content[3] = (byte)(temp.Length >> 8 & 0xFF);
Buffer.BlockCopy(temp, 0, content, 4, temp.Length);
}
return content;
}
就可以握手成功了。
参考:https://blog.csdn.net/qq_20282263/article/details/54310737