Ответ 1
Вы должны закрыть поток перед закрытием соединения:
tcpClient.GetStream().Close();
tcpClient.Close();
Закрытие клиента не закрывает поток.
Каков правильный способ закрыть или reset соединение TcpClient? У нас есть программное обеспечение, которое общается с оборудованием, но иногда что-то идет не так, и мы больше не общаемся с ним, пока не перезапустим программное обеспечение.
Я попытался заставить TcpClient.Close() и даже установить его в null, но это не работает. Выполняется только полный перезапуск программного обеспечения.
Предложения?
Я не могу использовать ключевое слово using, потому что TpcClient определяется только в одном месте, но используется во всей библиотеке. (И есть только одно соединение в любой момент времени)
Это библиотека, которая обрабатывает связь. Само программное обеспечение может вызывать метод ResetConnection() класса Controller (который представляет собой аппаратное обеспечение).
В настоящее время он выглядит как
if (tcpClient != null)
{
tcpClient.Close();
tcpClient = null;
}
Теперь из того, что я прочитал здесь, я должен использовать tcpClient.Dispose() вместо "= null"
Я дам эту попытку и посмотрю, имеет ли это значение.
Вы должны закрыть поток перед закрытием соединения:
tcpClient.GetStream().Close();
tcpClient.Close();
Закрытие клиента не закрывает поток.
Учитывая, что принятый ответ устарел, и я ничего не вижу в других ответах по этому поводу, я создаю новый. В .Net 2 и более ранних версиях вам пришлось вручную закрывать поток перед закрытием соединения. Эта ошибка исправлена во всех более поздних версиях TcpClient
на С#, и, как указано в документе о методе Close, вызов метода Close
закрывает как соединение, так и поток
РЕДАКТИРОВАТЬ в соответствии с Microsoft Docs
Метод Close помечает экземпляр как удаленный и запрашивает, чтобы соответствующий сокет закрыл TCP-соединение. Основываясь на свойстве LingerState, TCP-соединение может оставаться открытым некоторое время после вызова метода Close, когда данные еще предстоит отправить. Уведомление не предоставляется, когда базовое соединение завершило закрытие.
Вызов этого метода в конечном итоге приведет к закрытию соответствующего сокета, а также закроет связанный NetworkStream, который используется для отправки и получения данных, если они были созданы.
Используйте слово: using
. Хорошая привычка программировать.
using (TcpClient tcpClient = new TcpClient())
{
//operations
tcpClient.Close();
}
Закрывает соединение сокета и позволяет повторно использовать сокет:
tcpClient.Client.Disconnect(false);
За исключением некоторых внутренних протоколов, Close == Dispose.
Dispose вызывает tcpClient.Client.Shutdown(SocketShutdown.Both), но он ест любые ошибки. Возможно, если вы вызываете это напрямую, вы можете получить полезную информацию об исключении.
Правильный способ закрыть сокет, чтобы вы могли повторно открыть:
tcpClient.Client.Disconnect(true);
Логический параметр указывает, хотите ли вы повторно использовать сокет:
Несмотря на все соответствующие 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 ВСЕ соединения?