2009-04-21 4 views
0

Я использую метод BeginReceive() и EndReceive() для async IO с использованием Sockets в .NET. Клиент отправляет непрерывные пакеты данных, а вызов EndReceive() возвращает количество прочитанных байтов.Как избежать блокировки Socket.EndReceive(), когда нет данных

Проблема в том, что клиент отправляет пакеты данных, а длина данных - ZERO. Он нашел это, проанализировав трафик в WireShark. Когда длина данных равна нулю, вызов EndReceive() просто блокируется.

Есть ли способ идентифицировать данные длины ZERO без фактического блокирования на EndReceive()?

Кроме того, свойство ReceiveTimeout не работает на методы Async.

Пример исходного кода:

// This method runs on a separate thread 
private void ProcessRequest() 
{ 
    BeginReceive(OnClientReceive); 

    // Do some work here in a loop 
} 

// Callback method 
private void OnClientReceive(IAsyncResult result) 
{ 
    int receivedCount = socket.EndReceive(result); // this one blocks 

    // Do some work here 

    // Again start listening for data 
    BeginReceive(OnClientReceive); 
} 
+0

Я думаю, что Азиз ответил на ваш вопрос? Даже если клиент отправляет данные нулевой длины, EndRecieve должен запускаться и заканчиваться. Если клиент закрывает сокет до того, как он завершит отправку, EndRecieve должен выбросить исключение, когда ошибки сокета выходят из строя. Я думаю, что здесь происходит что-то еще ... Я думаю, что его блокирование, потому что клиент никогда не отправляет. Вы уверены, что клиент отправляет в тот же сокет, который ждет? – Jess

+0

Даже если клиент завершает отправку нулевых данных, он должен по-прежнему отправлять заголовок сообщения, а затем EndRecieve должен выбрать это и вернуть 0 байт. – Jess

+0

У вас есть контроль над кодом клиента? Можете ли вы поймать случай, когда данные являются нулевыми, и просто не отправлять его? Это может решить вашу проблему, но я снова думаю, что происходит что-то еще. – Jess

ответ

0

Розетки в .NET имеет дело с пакетами, как непрерывный поток данных, а не на пакет за пакетом основе. Вот почему EndReceive будет блокироваться до тех пор, пока данные не будут доступны, или пока соединение не будет завершено.

Если вы хотите, чтобы захватить полученные данные в базе пакетов по-пакет, я думаю, вам нужно использовать что-то вроде WinPcap библиотеки

+0

Это то, что я использую (WinpCap с WireShark), но проблема заключается не в захвате пакетов. Блоки EndReceive(), из-за которых мой поток блокируется. Я хочу выйти из этой блокировки. – A9S6

+0

Я не уверен, правильно ли я понимаю. Вы используете EndReceive() в обратном вызове StartReceive(), правильно? поэтому EndReceive() будет ждать, пока не будут прочитаны некоторые данные. Если есть какой-то код, который вы хотите выполнить независимо от того, имеете ли вы данные, то вы не должны помещать его в обратный вызов. Не могли бы вы объяснить, что вы пытаетесь захватить? – Aziz

+0

Да, у меня есть код, который выполняется после получения данных из EndReceive(). Но когда EndReceive() блокирует, данные не обрабатываются в методе обратного вызова, и он не генерирует исключение. Он просто ждет там. Кроме того, я думаю, что ReceiveTimeout не работает с EndReceive(). Я хочу, чтобы этот EndReceive() возвращал и не блокировал поток обратного вызова (даже если он возвращает ZERO). – A9S6

1

Я хотел бы проверить socket.Available

  1. if socket.Available > 0 процесс весь код ваш обратный вызов «OnClientReceive»
  2. if socket.Available = 0 только часть «// Выполнить работу здесь» должны быть обработаны
  3. поставить некоторые замки, чтобы избежать конфликтов
Смежные вопросы