C# WebSocket客户端无法握手

C# WebSocket客户端无法握手,c#,html,websocket,C#,Html,Websocket,我最近开始使用HTML5WebSocket,我有一个简单的jQueryWeb客户端和一个控制台应用服务器。在阅读了握手之后,以下是我目前为客户准备的: var socket = new WebSocket("ws://127.0.0.1:100", ["chat"]); socket.onopen = function() { console.log(socket.readyState); } 这会将以下内容发送到我的服务器: GET / HTTP/1.1 Upgrade: webso

我最近开始使用HTML5WebSocket,我有一个简单的jQueryWeb客户端和一个控制台应用服务器。在阅读了握手之后,以下是我目前为客户准备的:

var socket = new WebSocket("ws://127.0.0.1:100", ["chat"]);
socket.onopen = function() {
    console.log(socket.readyState);
}
这会将以下内容发送到我的服务器:

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1:100
Origin: http://localhost:57944
Sec-WebSocket-Protocol: chat
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: dBQ0epP7wmgHDEJc6Me95Q==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
现在,我的服务器代码

首先,我阅读上面从客户端发送的行,找到
Sec WebSocket Key
值并将其保存到我的变量
Key

然后我从中附加一个神奇的数字,它是258EAFA5-E914-47DA-95CA-C5AB0DC85B11。这将产生以下代码:

key = string.Concat(key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
using (SHA1 sha1 = SHA1.Create())
{
    byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(key));
    responseKey = Convert.ToBase64String(hash);
}
最后,我的响应密钥用于构造我发送回客户端的消息,即:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: u9guLPph1FeCPuOpFNs4F1b+UqY=
Sec-WebSocket-Protocol: chat
[blank line, as requested in spec]
但是,我的
socket.readyState
从0变为3,然后失败,出现以下错误
WebSocket连接到“ws://127.0.0.1:100/”失败:

我已经读到,这可能是由于我的服务器使用了与客户端不兼容的协议,但如果是这样的话,我不完全确定从哪里开始寻找。如果没有,是否有人知道如何解决这个问题,或者我可以去哪里获取更多信息,因为我有点困惑

2013年3月21日

在阅读了@djc下面的评论之后,我修改了服务器代码,以发送回带有以下内容的确认:

using (StreamWriter sw = new StreamWriter(ns, Encoding.UTF8))
{
    sw.NewLine = "\r\n\r\n";

    // get response and calculate responseKey here (getting bytes as UTF-8 from client)

    sw.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
    sw.WriteLine("Upgrade: websocket");
    sw.WriteLine("Connection: Upgrade");
    sw.WriteLine("WebSocket-Origin: http://localhost:57944");
    sw.WriteLine("WebSocket-Location: 127.0.0.1:100");
    sw.WriteLine("Sec-WebSocket-Accept: " + responseKey);
    sw.WriteLine("");
    sw.Flush();
}
好的,我不再在客户端上收到错误-但是'socket.readyState'保持在0,并且我的
socket.onopen
块从未被触发-尽管我看到客户端连接尝试通过。

基于我最终设法使它工作。这是我的客户代码:

var socket = new WebSocket("ws://localhost:8181/websession", ['chat','superchat']);

socket.onopen = function()
{
    $("div#messages").append("<p class=\"event\">Socket is connected.</p>");
    socket.send("Thanks!");
};

现在我获得了一个有效的连接,但无法通过服务器发送/接收数据-但我想这是另一种情况。

您是否尝试过不设置协议?(即停止聊天。)@djc对我来说很不幸,是的。在尝试之前,我没有聊天功能,同样的错误。也许你应该填写响应键,这样我可以用我自己的代码检查。(或另一对匹配的Sec WebSocket Key和Sec WebSocket Accept值。)@djc完成后,我再次运行并修改了客户端请求和服务器计算的值。好的,我的代码与您的代码匹配。您的响应是否以两组\r\n结尾?做得好,我实际上发现您不需要包含那些聊天和超级聊天协议,您只需要在响应结尾再添加一行。@EnglishMaster您完全正确,包含这些协议是一种误导,显然,我缺少的是一个非常重要的
\r\n\r\n
,表示传输结束。
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream stream = client.GetStream())
using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
using (StreamWriter sw = new StreamWriter(stream, Encoding.UTF8))
{
    Dictionary<string, string> headers = new Dictionary<string, string>();
    string line = string.Empty;
    while ((line = sr.ReadLine()) != string.Empty)
    {
        string[] tokens = line.Split(new char[] { ':' }, 2);
        if (!string.IsNullOrWhiteSpace(line) && tokens.Length > 1)
        {
            headers[tokens[0]] = tokens[1].Trim();
        }
    }

    string responseKey = "";
    string key = string.Concat(headers["Sec-WebSocket-Key"], "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
    using (SHA1 sha1 = SHA1.Create())
    {
        byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(key));
        responseKey = Convert.ToBase64String(hash);
    }

    sw.WriteLine("HTTP/1.1 101 Switching Protocols");
    sw.WriteLine("Upgrade: websocket");
    sw.WriteLine("Connection: Upgrade");
    sw.WriteLine("Sec-WebSocket-Accept: " + responseKey);
    sw.WriteLine("Sec-WebSocket-Protocol: chat");
    sw.WriteLine("");
    sw.Flush();
}