Как правильно и полностью закрыть / сбросить соединение TcpClient? - PullRequest
67 голосов
/ 08 января 2009

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

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

Предложения


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

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

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

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

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

Я попробую и посмотрю, имеет ли это значение.

Ответы [ 8 ]

76 голосов
/ 30 декабря 2009

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

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

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

21 голосов
/ 22 марта 2016

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

РЕДАКТИРОВАТЬ в соответствии с документами Microsoft

Метод Close помечает экземпляр как удаленный и запрашивает связанный сокет закроет TCP соединение. На основе LingerState В этом случае соединение TCP может оставаться открытым в течение некоторого времени после Метод close вызывается, когда данные еще предстоит отправить. Здесь нет уведомление предоставляется, когда базовое соединение завершено закрытие.

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

20 голосов
/ 08 января 2009

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

using (TcpClient tcpClient = new TcpClient())
{
     //operations
     tcpClient.Close();
}
7 голосов
/ 14 августа 2009

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

tcpClient.Client.Disconnect(false);
4 голосов
/ 24 июня 2016

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

tcpClient.Client.Disconnect(true);

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

Disconnect method usage

4 голосов
/ 09 января 2009

За исключением некоторых внутренних журналов, Закрыть == Удалить.

Утилизировать вызовы tcpClient.Client.Shutdown (SocketShutdown.Both), но он ест любые ошибки. Возможно, если вы позвоните напрямую, вы можете получить полезную информацию об исключениях.

3 голосов
/ 17 января 2018

Несмотря на наличие всех соответствующих операторов 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 })
   ...
0 голосов
/ 08 января 2009

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

И вы уверены, что у вас есть соединения TcpClient.Close () и TcpClient.Dispose () - ed ALL ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...