从服务器发送响应握手后,websocket.onopen未触发

从服务器发送响应握手后,websocket.onopen未触发,websocket,Websocket,下面我详细分享了我的代码。我阅读文档和所有关于握手的内容。我遵循了文档中给出的所有步骤和互联网上的许多示例,但仍然存在这个问题。奇怪的是,当我关闭服务器时,websocket.onclosse()被触发 //简单Websocket服务器 使用制度; 使用System.Collections.Generic; 使用System.Linq; 使用系统文本; 使用System.Net.Sockets; Net系统; 使用System.IO; 使用System.Security.Cryptograph

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


//简单Websocket服务器
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Net.Sockets;
Net系统;
使用System.IO;
使用System.Security.Cryptography;
使用系统线程;
命名空间WebSocketServer
{
班级计划
{
//港口
专用静态int_端口=8181;
静态void Main(字符串[]参数)
{
TcpListener t=新的TcpListener(IPAddress.Loopback,_端口);
t、 Start();
Console.WriteLine(“服务器已启动,正在等待客户端\n\n”);
字节[]buff=新字节[255];
网络流;
TCP客户机;
while(true)
{
client=t.AcceptTcpClient();
如果(!client.Connected)
返回;
//我需要形成一个适当的机制来从网络流中获取所有数据。
//如果我等待的时间太长,客户端就会断开连接,我们无法获得流,如果
//如果我们根本不等待,那么数据就不会到达服务器端口,因此无法访问
//读握手。
stream=client.GetStream();
while((stream.Read(buff,0,buff.Length))!=0)
{
打破
}
如果(0!=增益长度)
打破
}
StreamWriter writer=新StreamWriter(流);
writer.AutoFlush=true;
//while(stream.DataAvailable)
//读取流(buff,0,buff.Length);
WriteLine(System.Text.ascienceoding.ASCII.GetString(buff));
string clientHandshake=System.Text.ascienceoding.ASCII.GetString(buff);
字符[]分隔符=新字符[1];
分隔符[0]='\n';
字符串[]温度=clientHandshake.Split(分隔符,100);
string keyword=“Sec WebSocket Key”;
字符串键=”;
foreach(临时中的字符串s)
{
如果包含(关键字))
{
字符串keyTemp=s.Substring(关键字.Length+2);
键=键温移除(键温长度-1);
打破
}
}
字符串responseKey=GetServerResponseKey(键);
//发送服务器握手
串握手=
“HTTP/1.1 101交换协议\r\n”+
“升级:websocket\r\n”+
“连接:升级\r\n”+
Sec WebSocket接受:“+responseKey+”\r\n”;
写作(握手);
writer.Flush();
控制台。写线(握手);
while((stream.Read(buff,0,buff.Length))!=0)
{
打破
}
WriteLine(System.Text.ascienceoding.ASCII.GetString(buff));
//使服务器保持活动状态
while(true)
{ }
}
//将字符串转换为字节[]的帮助器方法
私有静态字节[]GetByteArray(字符串str)
{
UTF8Encoding=新的UTF8Encoding();
返回编码.GetBytes(str);
}
//需要此方法,因为它结合了密钥(从客户端获得)
//然后获取该字符串的SHA1哈希,然后编码为base64。
//这都是必需的,因为握手机制只能通过以下方式完成
//根据Websocket协议的方式(http://datatracker.ietf.org/doc/rfc6455/) 
私有静态字符串GetServerResponseKey(字符串键)
{
Console.WriteLine(“原始键=”+键);
string keyForHash=string.Concat(key,Guid.NewGuid());
Console.WriteLine(“服务器响应键的文本版本=“+keyForHash”);
UTF8Encoding=新的UTF8Encoding();
byte[]temp=encoding.GetBytes(keyForHash);
SHA1 hashProvider=新的SHA1CryptoServiceProvider();
字节[]keyForBase64=hashProvider.ComputeHash(临时);
返回Convert.tobase64字符串(keyForBase64);
}
}
}
//简单WebSocket客户端
var-ws;
函数btnConnectSend_onclick(){
如果(“窗口中的WebSocket”){
ws=newwebsocket(“ws://localhost:8181”);
ws.onopen=函数(){
警报(“连接打开”);
发送(“你好服务器”);
};
ws.onmessage=函数(evt){
form1.txtMessage.value=evt.data;
警报(“服务器显示:“+evt.data”);
};
ws.onclose=function(){
警报(“插座关闭!!!”;
};
ws.onerror=函数(){
警报(“WTF!”);
};
}
}
函数btnClose_onclick(){
ws.close();
};



我想您在
GetServerResponseKey()中有一个bug
keyForHash
应分配给
String.Concat(键,“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”)

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


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

很抱歉,simonc我在握手结束时遇到了这些问题,但问题仍然存在。我在实验时把它们注释掉了。我将更新源代码。无论如何,谢谢。澄清:在客户端握手中没有任何Sec WebSocket协议头。客户端握手如下所示:GET/demo HTTP/1.1升级:websocket连接:
// 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 client\n\n");

        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 Protocols\r\n" +
            "Upgrade: websocket\r\n" +
            "Connection: Upgrade\r\n" +
            "Sec-WebSocket-Accept: " + responseKey + "\r\n";

        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>