У меня есть система сбора данных, которая передает данные со сборного компьютера (сервера) на компьютер печати (клиент) по TCP-соединению.Код работает нормально при первом запуске коллекции.Код продолжает нормально работать при последующих запусках, если система не остается бездействующей более трех минут.Если система остается бездействующей более трех минут, передача зависает в течение первых 12 секунд или около того (достаточно долго, чтобы вызвать переполнение буферов сбора).
В начале каждой коллекции клиент зацикливается на 30 секунд, где он проверяет каждые 1 мс, чтобы определить, является ли _clientStream.DataAvailable = true.Этот цикл выглядит примерно так (некоторый код проверки ошибок удален):
public bool WaitForData(int maxWaitInMs)
{
DateTime start_time = DateTime.Now;
while (!_clientStream.DataAvailable )
{
Thread.Sleep(DATA_WAIT_DELAY); //1 ms
TimeSpan elapsed_time = DateTime.Now - start_time;
if (elapsed_time.TotalMilliseconds > maxWaitInMs)
{
return false;
}
}
return true;
}
На стороне сервера просто выполняется запись данных фиксированной длины
_dataTcpServer.SendData(packet_buffer, OFFSET, packet.Size());
Когда возникает проблема,По отладчику я могу сказать, что сервер вызывает SendData один раз, возвращает, получает следующий пакет данных, снова вызывает метод send, а затем в течение примерно 12 секунд зависает при вызове SendData.Тем временем клиент никогда не увидит, что DataAvailable сбывается, пока не пройдет 12 секунд.Время ожидания отправки оставлено по умолчанию, поэтому оно должно быть бесконечным.Кажется, что 12-секундный интервал в некоторой степени связан с количеством отправляемых данных.
Одна вещь, которую я сделал по-другому в этой системе, заключалась в том, что вместо создания TcpClient при запуске клиентского приложения я запускаю TcpClient, когда клиенту необходимо подключиться.При отключении я распоряжаюсь потоком, полученным через TcpCLient.GetStream, и закрываю TcpClient.
Я просто надеюсь на некоторое понимание того, почему бездействие в течение трех минут имеет такой эффект (обе системы работают под управлением XP).
РЕДАКТИРОВАТЬ - Проблема решена, но понимание становится неуловимым
На сервере я использовал отдельный поток, который использовал TcpListener.AcceptTcpClient () для подключения клиента.AcceptTcpClient () возвращает объект TcpClient.Я бы периодически проверял это свойство IsConnected в TcpClient, чтобы знать, отключился ли клиент (т. Е. Измерение завершено), а затем снова ожидал бы AcceptTcpClient () и ждал начала следующего измерения.Проблема заключалась в том, что, хотя TcpClient клиента был отключен, TcpClient.IsConnected сервера всегда возвращал значение true.
Я решил проблему, отправив клиенту сообщение (не через TCP) на сервер, а затем сервер принудительно отключил его.Теперь все работает, но я убежден, что я не использую этот API должным образом.Хотя я вижу методы асинхронного принятия, я не вижу, как сервер должен выяснять, когда клиент отключается, и не понимаю, почему свойство TcpClient.IsConnected сервера будет возвращать true, если больше нетдействительное соединение.
Также я опоздал, заметив свойство ExclusiveAddressUse, поэтому никогда не устанавливал его в значение true.Система действовала так, как если бы через несколько минут было установлено другое клиентское соединение, то же самое соединение использовалось повторно, и сервер мог отправлять данные клиенту (то есть, как будто клиент никогда не отключался).Если с момента разъединения прошло более трех минут, новое клиентское соединение было принято (хотя, насколько я могу судить, мой код никогда не возвращался в строку AcceptTcpClient ()), но это больше не было то же соединение, которым был серверотправка на.