Asp.net 套接字:.NET Core 2服务器,HTML5客户端无法连接

Asp.net 套接字:.NET Core 2服务器,HTML5客户端无法连接,asp.net,html,sockets,Asp.net,Html,Sockets,我遇到了套接字服务器的问题。希望你们能帮助我。 我有一个运行在Debian上的内置.NET内核的服务器,它对.NET中的客户端运行得很好,但当我尝试使用HTML客户端时,它总是无法通过握手 以下是我的示例服务器: class Program { public static TcpListener listener; private static List<ClientPacket> clients; private const int port = 4245;

我遇到了套接字服务器的问题。希望你们能帮助我。 我有一个运行在Debian上的内置.NET内核的服务器,它对.NET中的客户端运行得很好,但当我尝试使用HTML客户端时,它总是无法通过握手

以下是我的示例服务器:

class Program
{
    public static TcpListener listener;
    private static List<ClientPacket> clients;
    private const int port = 4245;
    private const int bufferSize = 1024;

    static void Main(string[] args)
    {
        clients = new List<ClientPacket>();
        listener = new TcpListener(IPAddress.Any, port);
        listener.Start();
        StartListening();

        while (true)
        {
        }
    }

    private static void StartListening()
    {
        listener.BeginAcceptTcpClient(AcceptClient, listener);
    }

    private static void AcceptClient(IAsyncResult res)
    {
        TcpClient client = listener.EndAcceptTcpClient(res);
        client.NoDelay = true;

        ClientPacket packet = new ClientPacket(client);
        clients.Add(packet);

        Console.WriteLine("Client connected");
        client.Client.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(ReceiveMessage), packet);
        StartListening();
    }

    private static void ReceiveMessage(IAsyncResult res)
    {
        ClientPacket packet = (ClientPacket)res.AsyncState;
        Socket s = packet.client.Client;

        try
        {
            if (s.EndReceive(res) > 0)
            {
                s.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(ReceiveMessage), packet);
            }
            else
            {
                clients.Remove(packet);
                s.Close();
                packet = null;
            }
        }
        catch (Exception e)
        {
            clients.Remove(packet);
            s.Close();
            packet = null;
        }

    }
类程序
{
公共静态TcpListener侦听器;
私有静态列表客户端;
专用常量int端口=4245;
私有常量int bufferSize=1024;
静态void Main(字符串[]参数)
{
clients=新列表();
侦听器=新的TcpListener(IPAddress.Any,端口);
listener.Start();
惊人的倾听();
while(true)
{
}
}
私有静态侦听()
{
beginacepttcpclient(AcceptClient,listener);
}
专用静态void AcceptClient(IAsyncResult res)
{
TcpClient client=listener.EndAcceptTcpClient(res);
client.NoDelay=true;
ClientPacket=新的ClientPacket(客户端);
添加(数据包);
Console.WriteLine(“客户端连接”);
client.client.BeginReceive(packet.buffer,0,bufferSize,0,新异步回调(ReceiveMessage),packet);
惊人的倾听();
}
专用静态无效接收消息(IAsyncResult res)
{
ClientPacket=(ClientPacket)res.AsyncState;
套接字s=packet.client.client;
尝试
{
如果(s.EndReceive(res)>0)
{
s、 BeginReceive(packet.buffer,0,bufferSize,0,新异步回调(ReceiveMessage),packet);
}
其他的
{
客户端。删除(数据包);
s、 Close();
数据包=空;
}
}
捕获(例外e)
{
客户端。删除(数据包);
s、 Close();
数据包=空;
}
}
它只接受客户端,将它们添加到列表中,并在连接断开后将它们删除。问题是当我尝试使用此HTML5客户端时(从示例教程复制):


函数WebSocketTest()
{
如果(“窗口中的WebSocket”)
{
var ws=newwebsocket(“ws://serverIP:4245”);
ws.onopen=函数()
{
ws.send(“要发送的消息”);
警报(“消息已发送…”);
};
ws.onmessage=函数(evt)
{ 
收到的var_msg=evt.data;
警报(“收到消息…”);
};
ws.onclose=function()
{ 
警报(“连接已关闭…”);
};
window.onbeforeunload=函数(事件){
socket.close();
};
}
其他的
{
警报(“您的浏览器不支持WebSocket!”);
}
}
问题是,我从未看到来自“onopen”函数的警报,所以它没有正确打开,readystatus一直保持为“正在连接”,而不是“已连接”

我读过一篇关于服务器响应的文章,其中包含一些确认和完成握手的哈希值,但在旧的.NET示例中看到了它,而不是在Core 2的TcpListener中看到的…所以我认为它是BeginAcceptTcpClient函数的一部分…由于它与.NET客户端一起工作,所以我不确定错误在哪里


有谁能帮我解决这个问题,或者告诉我如何实现握手哈希响应吗?

好的,我发现了一个问题。客户端确实希望有一个哈希响应来完成握手…仍然没有取消设置,以及为什么HTML和.NET客户端不需要它

我创建了一种新的握手方法,用于发送所需的响应:

private static void CompleteHandshake(IAsyncResult res)
{
    ClientPacket packet = (ClientPacket)res.AsyncState;
    Socket s = packet.client.Client;
    try
    {
        if (s.EndReceive(res) > 0)
        {
            var data = ByteArray.ReadString(packet.buffer);

            if (new Regex("^GET").IsMatch(data))
            {
                Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
                    + "Connection: Upgrade" + Environment.NewLine
                    + "Upgrade: websocket" + Environment.NewLine
                    + "Sec-WebSocket-Accept: "
                    + Convert.ToBase64String(
                            SHA1.Create().ComputeHash(
                                Encoding.UTF8.GetBytes(
                                    new Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
                                )
                            )
                    ) + Environment.NewLine
                    + Environment.NewLine);


                Console.WriteLine("Packet incoming");
                s.Send(response, 0, response.Length, SocketFlags.None);
            }
            s.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(ReceiveMessage), packet);
        }
        else
        {
            clients.Remove(packet);
            s.Close();
            packet = null;
        }
    }
    catch (Exception e)
    {
        clients.Remove(packet);
        s.Close();
        packet = null;
    }
}
然后,旧代码中唯一的更改是侦听器方法AcceptClient,其中简单更改BeginReceive的方法参数以重定向到CompleteHandshake

private static void AcceptClient(IAsyncResult res)
{
    TcpClient client = listener.EndAcceptTcpClient(res);
    client.NoDelay = true;

    ClientPacket packet = new ClientPacket(client);
    clients.Add(packet);

    client.Client.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(CompleteHandshake), packet);
    StartListening();
}

发送哈希响应后的新方法CompleteHandshake将重定向回旧的ReceiveMessage方法,在该方法中,您可以根据需要处理消息。

如果您将此方法编辑为包含您必须如何修改问题中的代码,则您将提供有用的答案。因此,链接可能会更改,并且将来其他人将不容易获得这些信息:。嗯,浏览器连接是一个WebSocket,.NET连接是一个纯TCP套接字。它们不一样。WebSocket是一个升级的HTTP连接,在TCP套接字上创建。耶,我花了一段时间才捕捉到它。:)
private static void AcceptClient(IAsyncResult res)
{
    TcpClient client = listener.EndAcceptTcpClient(res);
    client.NoDelay = true;

    ClientPacket packet = new ClientPacket(client);
    clients.Add(packet);

    client.Client.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(CompleteHandshake), packet);
    StartListening();
}