处理阻止.NET套接字的超时

时间:2010-08-26 12:19:59

标签: c# sockets networking

使用Accept方法创建的TcpClient实例用于管理客户端连接。当我需要终止服务器线程时会出现问题,因为它在接收呼叫时被阻止。

所以我设置了一个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 Send操作,属性 mSocket.Connected 也始终为false,导致外部循环终止(其他线程调用Disconnect方法终止服务器线程)。 / p>

我错过了什么?

3 个答案:

答案 0 :(得分:2)

问题是如果超时发生TcpClient断开连接。所以你的方法不行。 使用异步读/写功能或使用选择。

使用异步函数调用可能最简单的方法是这样的:

byte[] data = new byte[4096];
IASyncResult result = stream.BeginRead(data, 0, data.Length, null, null);
result.AsyncWaitHandle.WaitOne(<timeout value in ms>);
int bytes = stream.EndRead(result);

if (!result.IsCompleted)
  <timed out>
else
  <read data>
...

答案 1 :(得分:1)

答案 2 :(得分:0)

您应该查看链接到的Socket.Connected MSDN页面上的C#示例。它具有明显不同的方法实现,以确定套接字是否仍然连接。

// .Connect throws an exception if unsuccessful
client.Connect(anEndPoint);

// This is how you can determine whether a socket is still connected.
bool blockingState = client.Blocking;
try
{
    byte [] tmp = new byte[1];

    client.Blocking = false;
    client.Send(tmp, 0, 0);
    Console.WriteLine("Connected!");
}
catch (SocketException e) 
{
    // 10035 == WSAEWOULDBLOCK
    if (e.NativeErrorCode.Equals(10035))
        Console.WriteLine("Still Connected, but the Send would block");
    else
    {
        Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
    }
}
finally
{
    client.Blocking = blockingState;
}

Console.WriteLine("Connected: {0}", client.Connected);