4

我正在使用最新版本的 Chrome(websocket 版本 13)进行测试。

这是我的简单客户页面,位于http://127.0.0.1/folder/default.aspx

<script type="text/javascript">
    var socket = new WebSocket('ws://localhost:8181/websession');
    socket.onopen = function () {
        alert('handshake successfully established. May send data now...');
    };
    socket.onclose = function () {
        alert('connection closed');
    };
    socket.onmessage = function(msg) {
        alert(msg);
    };
</script>

这是我的听众 (c#)

var listener = new TcpListener(IPAddress.Loopback, 8181);
listener.Start();
while (true)
{
    Console.WriteLine("Listening...");
    using (var client = listener.AcceptTcpClient())
    using (var stream = client.GetStream())
    using (var reader = new StreamReader(stream))
    using (var writer = new StreamWriter(stream))
    {
        writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
        writer.WriteLine("Upgrade: WebSocket");
        writer.WriteLine("Connection: Upgrade");
        writer.WriteLine("WebSocket-Origin: http://127.0.0.1");
        writer.WriteLine("WebSocket-Location: ws://localhost:8181/websession");
        writer.WriteLine("");
    }
    Console.WriteLine("Finished");
}

当我运行服务器,然后加载客户端页面时,它只显示"connection closed".

有人可以告诉我如何让这个握手正确执行吗?据我从文档和以前的问题中可以看出,我发回给客户的响应看起来是正确的。

4

3 回答 3

3

根据您的代码,这应该可以工作(至少使用 chrome)

var listener = new TcpListener(IPAddress.Loopback, 8181);
listener.Start();
while (true)
{
    Console.WriteLine("Listening...");
    using (var client = listener.AcceptTcpClient())
    using (var stream = client.GetStream())
    using (var reader = new StreamReader(stream))
    using (var writer = new StreamWriter(stream))
    {

        string line = null, key = "", responseKey = "";
        string MAGIC_STRING = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
        while (line != "")
        {
            line = reader.ReadLine();
            if (line.StartsWith("Sec-WebSocket-Key:"))
            {
                key = line.Split(':')[1].Trim();
            }
        }

        if (key != "")
        {
            key += MAGIC_STRING;
            using (var sha1 = SHA1.Create())
            {
                responseKey = Convert.ToBase64String(sha1.ComputeHash(Encoding.ASCII.GetBytes(key)));
            }
        }

        // send handshake to the client
        writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
        writer.WriteLine("Upgrade: WebSocket");
        writer.WriteLine("Connection: Upgrade");
        writer.WriteLine("WebSocket-Origin: http://127.0.0.1");
        writer.WriteLine("WebSocket-Location: ws://localhost:8181/websession");
        if (!String.IsNullOrEmpty(responseKey)) 
            writer.WriteLine("Sec-WebSocket-Accept: " + responseKey);
        writer.WriteLine("");

        writer.Flush();

        SendString(stream, "This code works!!!!");
        SendString(stream, "This code also works!!!! ".PadRight(300, '.') + "\r\nEND");
    }
    Console.WriteLine("Finished");
}


void SendString(Stream s, string str)
{
    var buf = Encoding.UTF8.GetBytes(str);
    int frameSize = 64;

    var parts = buf.Select((b, i) => new { b, i })
                   .GroupBy(x => x.i / (frameSize - 1))
                   .Select(x => x.Select(y => y.b).ToArray())
                   .ToList();

    for (int i = 0; i < parts.Count; i++ )
    {
        byte cmd = 0;
        if (i == 0) cmd |= 1;
        if (i == parts.Count - 1) cmd |= 0x80;

        s.WriteByte(cmd);
        s.WriteByte((byte)parts[i].Length);
        s.Write(parts[i], 0, parts[i].Length);
    }

    s.Flush();
}

PS:使用

socket.onmessage = function(msg) {
    alert(msg.data);
};

查看服务器发送的消息内容。

于 2012-11-22T21:37:37.787 回答
2

您尚未计算安全哈希。客户端向您发送一个号码,并且在规范中硬编码了另一个号码。您需要按照规范中的说明组合它们,并将其作为标题返回。

这表明您的服务器实际上是一个 web-socket 服务器。

RFC6455

请注意,除了 RFC,您可能还需要考虑是否实现 Hixie 76。

于 2012-11-22T17:56:33.717 回答
1

Dispose 上的 StreamReader 和 StreamWriter 正在关闭底层流(NetworkStream)。所以客户端页面只显示“连接关闭”

于 2013-07-03T20:19:19.637 回答