Я разрабатываю серверное приложение на С#. Клиенты могут подключаться к серверу и выполнять различные запросы. В настоящее время, когда клиент подключается, я создаю новый поток для обработки запросов (запросов). Я использую класс TCPClient для обработки клиентских подключений. Мой сервер работает следующим образом:
Моя проблема заключается в следующем:
Когда я прочитаю из объекта NetworkStream, который я получаю из класса TCPClient, метод NetworkStream Read() не блокирует, если нет доступных данных. Когда сервер достигает шага №3, я хотел бы установить некоторый тайм-аут в NetworkStream, и если клиент не сделает больше запросов в течение этой продолжительности, сервер должен убить соединение, когда будет выбрано это исключение таймаута. Когда мой сервер достигает шага 3, метод NetworkStream Read() не блокирует, независимо от того, что я установил для него свойство ReadTimeout. Может ли кто-нибудь помочь мне или предложить лучший способ сделать то, что я пытаюсь сделать.
Спасибо
NetworkStream.Read и ReadByte должны блокироваться до таймаута, если нет данных для чтения. Я думаю, что гораздо более вероятно, что звонок что-то читает, вероятно, пучок нулей. Проверьте данные, отправляемые клиентом тщательно.
Чтобы принудительно заблокировать NetworkStream, когда нет доступных данных:
TcpClient clientConnection = new TcpClient();
if(clientConnection.Available > 0)
{
//You want to continue execution even though there is no available data to be read from the server then:
clientConnection.Client.Blocking = false;
}
Это то, что вы ищете?
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.receivetimeout.aspx
Похоже, вы получаете NetworkStream из TcpClient с помощью GetStream(), а затем вызываете метод Read() на нем.
Оберните NetworkStream в BufferedStream. BufferedStream.Read будет блокироваться, пока не будет доступно по крайней мере 1 байт.
Вам потребуется обработать "тайм-аут" самостоятельно, так как NetworkStream.Read() не предоставляет способ сделать это.
То, что вы, вероятно, захотите сделать в потоке клиента, - это использование некоторой комбинации NetworkStream.DataAvailable и/или NetworkStream.CanRead в сочетании с механизмом блокировки/тайм-аута (например, с использованием вызова WaitHandle.WaitOne с таймаутом) чтобы предоставить клиенту время для предоставления данных. Если через определенное время ничего не приходит, просто выключите соединение и выйдите.
Вы должны прекратить использование метода Read() для метода BeginRead() и изучить параллельную обработку. Сетевое программирование не для слабонервных.
В принципе, вы не хотите создавать опрос циклов для данных.
while(!timedout && !stream.DataAvailable) sleep(0); // This is bad.
if(steam.DataAvailable) steam.Read();
Вместо этого имеет смысл делать что-то подобное. Создайте событие reset, вызовите BeginRead() и отпустите событие reset в обратном вызове. Что-то вроде следующего:
void clientThread()
{
stream.BeginRead(myCallback);
resetEvent.WaitOne(timeout)
}
void myCallback
{
resetEvent.Set();
}