2013-12-13 2 views
1

Я в ситуации, когда мне нужно открыть поток между моим слушателем и TCPClient. Как только поток будет открыт, клиент отправит поток сообщений, и я отправлю ACK для каждого. Если я не получаю никаких сообщений за определенное количество времени (по умолчанию 5 минут), я отключусь от сервера и вернусь к прослушиванию нового соединения.Определение того, был ли отключен поток TCP

У слушателя должен быть только один Клиент, который пытается связаться с ним. В спецификациях указано, что поток должен быть открыт и удерживаться до тех пор, пока все сообщения не будут отправлены, и это может означать, что устройство подключено в течение нескольких дней или дольше. К сожалению, Клиент является сторонним программным обеспечением, и я не могу гарантировать, что он не будет закрывать соединение после каждого сообщения.

Мой вопрос: как я могу определить, отключен ли клиент. Я сделал свое исследование и знаю, что есть несколько ответов на этот вопрос, но они в основном говорят, что мне нужно писать в поток, и если есть исключение, соединение было закрыто. Я написал код для этого, но выяснил, что некоторые из клиентов не настроены для обработки входящих сообщений, которые не являются ACK. Пока все, что я получаю, регистрируются сообщения об ошибках, но я боюсь, что этот «ping» может привести к сбою одного из клиентов.

Я могу закрыть соединение после каждого сообщения, но по крайней мере один из Клиентов будет продолжать пытаться отправлять все сообщения в серии, пока все они не будут получены в одном потоке, поэтому он не будет работать с этим решением ,

Я могу установить NetworkStream.ReadTimeout на небольшое значение, подобное 1 секунде, но каждый раз, когда он истекает время, было бы исключение, а использование Исключения для управления потоком - это не хороший код (хотя я делаю немного это при пинге).

Ниже приведен фрагмент кода, что у меня сейчас:

while (bytesRead == 0 && isConnected && isListening) 
{ 
    if (stream.CanRead && stream.DataAvailable) 
    bytesRead = stream.Read(receivedBytes, 0, BufferSize); 
    else 
    { 
     if (++pingCount % 100 == 0) 
     { 
      // Ping the server every 10 seconds to confirm the connection 
      pingCount = 0; 
      try 
      { 
       stream.Write(ping, 0, ping.Length); 

       // client.Connected gives the status of the connection at the last communication 
       if (!client.Connected) 
        isConnected = false; 
      } 
      catch (Exception) 
      { 
       // If an exception is thrown, then the connection is closed 
       isConnected = false; 
      } 
     } 
     Thread.Sleep(100);  // Wait and try again 
    } 
} 
+0

Это звучит катастрофой в процессе создания. Если вы не можете согласиться на такие очень простые вещи, тогда вам будет нужно потратить время на то, чтобы он работал. Напишите спецификацию, сделайте это трудно. –

+0

Я согласен с тем, что было бы намного проще, если бы мы могли это сделать, но мы работаем с несколькими разными ранее существующими Клиентами и должны быть как можно более универсальными, потому что мы не знаем, какое программное обеспечение будет отправлять сообщения, только содержимое сообщения. – Tim

ответ

1

После немного больше поисков, мне удалось узнать, как получить доступ к гнездо из TcpClient. После этого я смог использовать опрос, чтобы подтвердить, что соединение все еще открыто. Мой код ниже:

try 
{ 
    if (client.Client.Poll(1000, SelectMode.SelectRead) && client.Client.Available == 0) 
    { 
     isConnected = false; 
    } 
} 
catch (Exception) 
{ 
    // If an exception is thrown, then the connection is closed 
    isConnected = false; 
} 

Client.Poll возвращает истину, если соединение закрывается, сброс прекращен, до или есть доступные данные. Если вы проверяете Client.Available и нет данных, соединение должно быть закрыто. Это не безупречно, но работает для моих целей, так как я просто возвращаюсь к слушанию.

Это решение взято из zendar, и есть here.

Смежные вопросы