在我从服务器发送响应握手后,websocket.onpen不会触发



下面我详细分享了我的代码。我阅读了有关握手的文档和所有内容。我遵循了文档中给出的所有步骤和互联网上的许多例子,但我仍然有这个问题。奇怪的是,当我关闭服务器时,id为websocket.onlosse()被触发了。


// Simple Websocket server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
namespace WebSocketServer
{
class Program
{
    //port 
    private static int _port = 8181;
    static void Main(string[] args)
    {
        TcpListener t = new TcpListener(IPAddress.Loopback, _port);
        t.Start();
        Console.WriteLine("Server is started and waiting for clientnn");
        byte[] buff = new byte[255];
        NetworkStream stream;
        TcpClient client;
        while(true)
        {
            client = t.AcceptTcpClient();
            if (!client.Connected)
               return;
            // I need form a proper mechanism to get all the data out of network stream.
            // If I wait too long client get disconnected and we dont get stream and if
            // if we dont wait at all then data doesnt reach server port and hence cant
            // read the handshake.
            stream = client.GetStream();
            while ((stream.Read(buff, 0, buff.Length)) != 0)
            {
                break;
            }
            if (0 != buff.Length)
                break;
        }
        StreamWriter writer = new StreamWriter(stream);                  
        writer.AutoFlush = true;

        //while (stream.DataAvailable)
            //stream.Read(buff, 0, buff.Length);
        Console.WriteLine(System.Text.ASCIIEncoding.ASCII.GetString(buff));
        string clientHandshake = System.Text.ASCIIEncoding.ASCII.GetString(buff);
        char[] separators = new char[1];
        separators[0] = 'n';
        string[] temp = clientHandshake.Split(separators, 100);
        string keyword = "Sec-WebSocket-Key";
        string key = "";
        foreach (string s in temp)
        {
            if (s.Contains(keyword))
            {
                string keyTemp= s.Substring(keyword.Length + 2);
                key = keyTemp.Remove(keyTemp.Length - 1);

                break;
            }
        }
        string responseKey = GetServerResponseKey(key);
        // Send Server handshake
        string handshake =
            "HTTP/1.1 101 Switching Protocolsrn" +
            "Upgrade: websocketrn" +
            "Connection: Upgradern" +
            "Sec-WebSocket-Accept: " + responseKey + "rn";
        writer.Write(handshake);
        writer.Flush();
        Console.WriteLine(handshake);
        while ((stream.Read(buff, 0, buff.Length)) != 0)
        {
            break;
        }
        Console.WriteLine(System.Text.ASCIIEncoding.ASCII.GetString(buff));

        // Keep Server alive
        while (true)
        { }
    }
    //Helper method to convert string into Byte[]
    private static byte[] GetByteArray(string str)
    {
        UTF8Encoding encoding = new UTF8Encoding();
        return encoding.GetBytes(str);
    }
    //This method is requuired because it combines key(got it from client)
    //with GUID. Then takes SHA1 hash of that string and then encode to base64.
    //This is all required because Handshake mechanism can be done by only this 
    //way according to Websocket Protocol(http://datatracker.ietf.org/doc/rfc6455/) 
    private static string GetServerResponseKey(string key)
    {
        Console.WriteLine("original key = " + key);
        string keyForHash = String.Concat(key, Guid.NewGuid());
        Console.WriteLine("text version of server response key = " + keyForHash);
        UTF8Encoding encoding = new UTF8Encoding();
        byte[] temp = encoding.GetBytes(keyForHash);
        SHA1 hashProvider = new SHA1CryptoServiceProvider();
        byte[] keyForBase64 = hashProvider.ComputeHash(temp);
        return Convert.ToBase64String(keyForBase64);
    }
}
}
// Simple WebSocket Client
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebSocketClient._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
<script language="javascript" type = "text/javascript">
    var ws;
    function btnConnectSend_onclick() {
        if ("WebSocket" in window) {
            ws = new WebSocket("ws://localhost:8181");
            ws.onopen = function() {
                alert("Connection Open");
                ws.send("Hello Server");
            };
            ws.onmessage = function(evt) {
                form1.txtMessage.value = evt.data;
                alert("Server says:" + evt.data);
            };
            ws.onclose = function() {
                alert("Socket Closed!!!");
            };
            ws.onerror = function() {
                alert("WTF!");
            };
        }
    }
    function btnClose_onclick() {
        ws.close();
    };
</script>
</head>
<body>
<form id="form1" runat="server">
<div style="height: 350px">
    <input id="btnConnectSend" type="button" value="Connect/Send" onclick ="return btnConnectSend_onclick ()"/>
    <br />
    <input id="txtMessage" type="text"/>
    <br />
    <input id="btnClose" type="button" value="Close" onclick="return btnClose_onclick()"/>
</div>
</form>
</body>
</html>

我认为GetServerResponseKey()中有一个错误。keyForHash应分配给String.Concat(key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")

附加到客户端密钥的值必须经过硬编码,并且不能是动态生成的guid。参见规范第4.2.2节第5点

另一点,您应该考虑检查Sec-WebocketProtocol标头的请求。如果这是由客户端发送的,它会期望您在握手响应中回显标头(当然,总是假设您的服务器支持子协议)。这不会导致握手暂停,但稍后可能会导致客户端拒绝您的握手响应。

相关内容

  • 没有找到相关文章

最新更新