我尝试向我的服务器添加一项功能,以启动特定客户端。但是客户端线程中的Read
函数阻塞了循环,客户端的踢脚命令将被执行,直到客户端发送另一条消息。所以我把它添加到服务器中的客户端线程中; (顺便说一下,我真的不明白为什么我应该把Poll
放在那里但是没有它就会抛出错误。)
if (client.Socket.Poll(10, SelectMode.SelectRead))
{
readMessageSize = client.Stream.Read(readMessage, 0, _packetSize);
}
else
{
if (client.Kicked)
{
Console.WriteLine("The client [" + client.IP + "] has been kicked.");
break;
}
Thread.Sleep(10);
continue;
}
这一次,它在客户端的构造函数上给出了一个错误(这个构造函数将从Accept()
函数返回的套接字作为参数)说:"不允许在非客户端执行操作阻止套接字。"。所以,我暂时将Blocking设置为true;
public ClientSocket(Socket client)
{
_socket = client;
_socket.Blocking = true;
try
{
Stream = new NetworkStream(_socket);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
_socket.Blocking = false;
}
我还将侦听器套接字的阻塞设置为false并更改它,因为当我尝试Abort()
侦听器线程时,它不会被激活,因为它被Accept()
所困扰
while (Running)
{
try
{
if (_socket.Poll(10, SelectMode.SelectRead))
{
var newClientSocket = _socket.Accept();
AddClient(newClientSocket);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
StopListen();
break;
}
Thread.Sleep(250);
}
我觉得我在实施服务器方面走错了路。我准备听取任何建议。我也可以接受任何可能对我有帮助的开源项目或代码片段。
答案 0 :(得分:1)
关于您发布的代码:
NetworkStream
对象的非阻塞套接字,那么设置一个套接字,你已经被NetworkStream
设置为非阻塞,这只会导致问题Socket.Poll()
方法正确地执行此操作,但请务必注意,"微秒"之间的差异非常重要。 (在Poll()
方法中使用)和"毫秒" (几乎在.NET中用于整数时间间隔的其他地方)。也许你真的想在Poll()
方法中等待10微秒,但是你的帖子并不完全清楚你的意图,所以我想确保你知道差。正确的方法是:
NetworkStream
,因此最明显的方法是使用ReadAsync()
方法。Socket.Shutdown()
方法,等待客户端关闭其结束(即,您看到完成的接收操作的长度为0字节)。但是,如果必须(例如Socket.Close()
),您可能会重置连接。这两种方法都会导致异步读取操作完成,从而可以清理客户端信息。