Как правильно и полностью закрыть / сбросить соединение TcpClient?


Как правильно закрыть или сбросить соединение TcpClient? У нас есть программное обеспечение, которое взаимодействует с оборудованием, но иногда что-то идет не так, и мы больше не будем общаться с ним, пока мы не перезапустим программное обеспечение.

Я попытался заставить TcpClient.Close() и даже установив его в null, но это не работает. Работает только полный перезапуск программного обеспечения.

предложения?


Я не могу использовать ключевое слово using, потому что TpcClient определяется только в одном месте, но используется во всей библиотеке. (И есть только одно соединение в любой момент времени)

это библиотека, которая обрабатывает сообщения. Само программное обеспечение может вызвать метод ResetConnection () класса контроллера (который представляет аппаратное обеспечение).

в настоящее время это выглядит как

if (tcpClient != null)
{
    tcpClient.Close();
    tcpClient = null;
}

теперь из того, что я прочитал здесь, я должен использовать tcpClient.Dispose () вместо "= null"

Я дам это попробовать и посмотреть, если это изменить ситуацию.

8 61

8 ответов:

вы должны закрыть поток перед закрытием соединения:

tcpClient.GetStream().Close();
tcpClient.Close();

закрытие клиента не закрывает поток.

использовать слова: using. Хорошая привычка к программированию.

using (TcpClient tcpClient = new TcpClient())
{
     //operations
     tcpClient.Close();
}

учитывая, что принятый ответ устарел, и я ничего не вижу в других ответах по этому поводу, я создаю новый. В .Net 2 и ранее вам приходилось вручную закрывать поток перед закрытием соединения. Эта ошибка исправлена во всех более поздних версиях TcpClient В C# и как указано в документе close метод вызов метода Close закрывает как соединение, так и поток

закрывает соединение сокета и позволяет повторно использовать сокет:

tcpClient.Client.Disconnect(false);

за исключением некоторых внутренних журналов, Close = = Dispose.

Dispose вызывает tcpClient.Клиент.Команда Shutdown( SocketShutdown.Оба ), но его съедает любые ошибки. Возможно, если вы вызовете его напрямую, вы можете получить полезную информацию об исключениях.

правильный способ закрыть сокет, чтобы вы могли снова открыть:

tcpClient.Client.Disconnect(true);

логический параметр указывает, хотите ли вы повторно использовать сокет:

Disconnect method usage

несмотря на наличие всех соответствующих using заявления, назвав Close, имея некоторую экспоненциальную логику отступления и воссоздавая TcpClient Я все еще вижу проблемы, когда приложение не может восстановить TCP-соединение без перезагрузки приложения. Он не справляется с System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

но есть вариант LingerState на TcpClient похоже, что это, возможно, решило проблему (возможно, не знаю в течение нескольких месяцев, так как моя собственная установка оборудования только терпит неудачу часто!). Смотрите MSDN.

// This discards any pending data and Winsock resets the connection.
LingerOption lingerOption = new LingerOption(true, 0);

using (var tcpClient = new TcpClient 
       {SendTimeout = 2000, ReceiveTimeout = 2000, LingerState = lingerOption })
   ...

вы пробовали звонить TcpClient.Dispose () явно?

и вы уверены, что у вас есть TcpClient.Close() и объект TcpClient.Dispose () - ed все подключения?