c# - WebSocket 客户端握手失败

标签 c# html websocket

我最近开始使用 HTML5 WebSockets,并且我有一个简单的 jQuery Web 客户端和一个控制台应用程序服务器。在阅读了有关握手的信息后,以下是我目前为客户提供的信息:

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 中。

然后我附加 Wikipedia article here 中的魔数(Magic Number)这是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);
}

最后,我的响应 key 用于构造我发送回客户端的消息,即:

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/' 失败:.

我读到这可能是因为我的服务器使用了与客户端不兼容的协议(protocol),但我不完全确定如果是这种情况从哪里开始查找。如果没有,有谁知道如何解决这个问题,或者我可以去哪里获取更多信息,因为我有点困惑。

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 block 从未被触发 - 尽管我看到客户端连接尝试即将到来通过。

最佳答案

基于this specification我终于让它工作了。这是我的客户端代码:

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!");
};

似乎需要包含用于 cookie 管理的 websession['chat','superchat'] 协议(protocol)。

服务器:

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();
}

现在我获得了有效的连接,但无法与服务器发送/接收数据 - 但我猜这是另一个故事了。

关于c# - WebSocket 客户端握手失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15504448/

相关文章:

websocket - PureScript Halogen 和 websockets

javascript - 从 websocket 获取过去的消息

c# - IIS 日志中的 WebAPI 路由

c# - MSTest 的全局测试初始化​​方法

HTTP/1.1 426 需要升级

javascript - Http 状态未在 try 和 catch javascript 上触发

javascript - Chrome 的 HTML5 canvas 绘图问题

c# - 在 Linq 表达式中使用方法

c# - 为什么事件目录搜索结果返回 1000 条记录

html - 当 SASS 重新编译 CSS 时,Chrome 的 "Auto-Reload Generated CSS"没有重新加载页面