Тайм-аут обработки при блокировке сокета .NET - PullRequest
3 голосов
/ 26 августа 2010

Экземпляр TcpClient, созданный методом Accept, используется для управления клиентским подключением.Проблема возникает, когда мне нужно прервать поток сервера, так как он блокируется при получении вызова.

Поэтому я настраиваю TcpClient ReceiveTimeout для выполнения цикла каждые n миллисекунд для проверкиусловие выхода.В результате операция Receive вызывает исключение (SocketException), имеющее код ошибки SocketError.TimedOut.Хорошо, я думал ...

Проблема в том, что свойство 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 для завершения потока сервера).

Чего мне не хватает?

Ответы [ 2 ]

2 голосов
/ 26 августа 2010

Проблема заключается в том, что в случае истечения времени ожидания TcpClient отключается.Так что ваш метод не сработает.Используйте асинхронные функции чтения / записи или используйте select.

Вероятно, самый простой способ вызова асинхронной функции такой:

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>
...
0 голосов
/ 26 августа 2010

Посмотрите пример C # на странице Socket.Connected MSDN, на которую вы ссылаетесь.В нем существенно отличается реализация метода определения того, подключен ли сокет.

// .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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...