使用Accept方法创建的TcpClient实例用于管理客户端连接。当我需要终止服务器线程时会出现问题,因为它在接收呼叫时被阻止。处理阻塞.NET套接字的超时时间
因此,我设置了一个TcpClient ReceiveTimeout以循环每个n毫秒来测试退出条件。结果是Receive操作引发了一个具有错误代码SocketError.TimedOut的异常(SocketException)。好,我在想......
的问题是,Socket.Connected返回false,但作为MSDN文档中规定的属性:
Connected属性的值反映了作为连接的状态最近的操作。如果您需要确定连接的当前状态,请进行非阻塞的零字节发送呼叫。如果调用成功返回或抛出WAEWOULDBLOCK错误代码(10035),那么套接字仍然连接;否则,套接字不再连接。
所以,我做什么规定:
try {
// Receive operation on socket stream
// Send operation on socket stream
} catch (SocketException e) {
if (e.SocketErrorCode == SocketError.TimedOut) {
try {
IAsyncResult asyncResult;
int sResult;
asyncResult = mSocket.Client.BeginSend(new byte[] {}, 0, 0, SocketFlags.None, delegate(IAsyncResult result) { }, null);
sResult = mSocket.Client.EndSend(asyncResult);
Debug.Assert(asyncResult.IsCompleted == true);
if (mSocket.Connected == false)
throw new Exception("not more connected"); // Always thrown
} catch (Exception e) {
// ...
}
}
但是,即使执行aynch发送操作,财产mSocket.Connected永远是假的,导致外环终止(其它线程调用Disconnect方法来终止服务器线程)。
我错过了什么?
恭候您的第一个答案!但这正是我试图避免的。对于使用非阻塞套接字,我会重构服务器逻辑并使每个网络操作异步,而不会产生额外的线程。 “问题是如果发生超时TcpClient断开连接”:它写在哪里?在stdc非阻塞套接字中,在超时(使用select实现)之后,不会断开连接。 – Luca 2010-08-26 13:20:44
我发布的代码使用异步BeginRead/EndRead函数。但它阻止使用WaitOne。所以你不必改变你的服务器逻辑。 BeginRead不会阻止。 WaitOne阻塞,直到出现数据或发生指定的超时。使用!result.IsCompleted来检查它是否超时或有数据可用。 – pitt7 2010-08-26 14:07:25
我不知道“如果发生超时,TcpClient断开连接”在哪里写入。但我有完全相同的问题。如果Read由超时返回,则连接为False。我没有对此做过多的研究,只是认为C#中并没有设置超时值,并定期运行到这个超时。 – pitt7 2010-08-26 14:11:04