Asp.net 套接字:.NET Core 2服务器,HTML5客户端无法连接
我遇到了套接字服务器的问题。希望你们能帮助我。 我有一个运行在Debian上的内置.NET内核的服务器,它对.NET中的客户端运行得很好,但当我尝试使用HTML客户端时,它总是无法通过握手 以下是我的示例服务器: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;
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();
}