Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [Все]   Вниз
  Печать  
Автор Тема: Проблема с сокетами.  (Прочитано 47578 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Mike_mvk
Гость
« : 18-10-2004 14:07 » 

Описываю обстановку.
Есть некий девайс, соединенный с компом по Ethernet. Умеет общаться по протоколу UDP. Между компом и девайсом два потока данных: команды управления девайсом ( полудуплекс с квитированием ) и поток некой информации от девайса.
На компе программа с 3 сокетами (winapi). 2 на команды управления, 1 для приема информации от девайса (обмен только в одну сторону). Сокеты живут в разных потоках.

Описываю проблему.
От девайса идет поток пакетов информации. При обмене командами управления, при чтении из сокета для приема информации, наблюдается исчезновение некоторых пакетов. Перехват (winpcap'ом) показывает, что пакеты до сетевой доходят.
Увеличение буфера
Код:
nParam = 524288;
setsockopt( sock, SOL_SOCKET,  SO_RCVBUF, (char*)&nParam, sizeof(nParam));
результата не дало.

Есть ли у Вас какие-нить мысли?
Если нужно, покажу куски кода.

ЗЫ Надеюсь на помощь и сочувствие...
ЗЗЫ Надеюсь, что понятно объяснил.
« Последнее редактирование: 02-12-2007 14:11 от Алексей1153++ » Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #1 : 18-10-2004 14:15 » 

давай поглядим код который читает данные из буфера tcp (там где идет прием данных)
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #2 : 18-10-2004 15:48 » 

Там не tcp. Там тоже UDP.
Код:
while( Running )
  {
nParam = sizeof( SOCKADDR_IN );
if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )
{
TRACE( WSAGetLastError() );
continue;
}
   if( !Running )
      break;
//далее обработка пакета
...
« Последнее редактирование: 02-12-2007 14:15 от Алексей1153++ » Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 18-10-2004 15:49 » 

Mike_mvk, wincap показывает, на какие адреса и порты идут пропавшие пакеты?
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Mike_mvk
Гость
« Ответ #4 : 19-10-2004 05:45 » 

Девайс немного туповат. Что такое ARP не знает, поэтому шлет бродкастом. Для приема инфы открыт порт 100.

Привожу код инициализации этого сокета.
Код:
if( WSAStartup ( MAKEWORD( 2, 2 ), &wsaData ) != 0 )
  return TRACE( WSAGetLastError() );

  sock = WSASocket( AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, 0, WSA_FLAG_OVERLAPPED );
  if( sock == INVALID_SOCKET )
  return TRACE( WSAGetLastError() );

//здесь я увеличивал приемный буфер. на пропадание пакетов это не влияет
  nParam = 524288;
  if( setsockopt( sock, SOL_SOCKET,  SO_RCVBUF, (char*)&nParam, sizeof(nParam)) != 0 )
  return TRACE( WSAGetLastError() );
   
  addr.sin_family = AF_INET ;
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr.sin_port = htons(100);

  if( bind( sock, (LPSOCKADDR) &addr, sizeof( addr ) ) != 0 )
  return TRACE( WSAGetLastError() );

WinPcap показывает, что девайс шлет все честно, однако при обмене по другим сокетам в программе не все пакеты читаются из этого сокета.
« Последнее редактирование: 02-12-2007 14:16 от Алексей1153++ » Записан
darkelf
Молодой специалист

no
Offline Offline

« Ответ #5 : 19-10-2004 05:58 » 

Скорее всего Вы просто не успеваете выбирать данные.
Записан
Mike_mvk
Гость
« Ответ #6 : 19-10-2004 07:08 » 

Цитата: darkelf
Скорее всего Вы просто не успеваете выбирать данные.


Не уверен. Поток данных всего около 8 кб/с. Заполнить такой буфер нереально. Да и программа много ресурсов не жрет.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #7 : 19-10-2004 07:31 » 

Mike_mvk, да кто ж так данные принимает...
Цитата
Код:
while( Running )
  {
      nParam = sizeof( SOCKADDR_IN );
      if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )
      {
         TRACE( WSAGetLastError() );
         continue;
      }
   if( !Running )
      break;
//далее обработка пакета
...
надо типа такого
Код:
while( Running )
{
nParam = sizeof( SOCKADDR_IN );
int length = sizeof( PACKET );
char * buffer = (char *) &bp;
while (length > 0)
{
int recv_now = recvfrom( sock, buffer + length, length, 0, &addr, &nParam );
if (recv_now == SOCKET_ERROR )
{
TRACE( WSAGetLastError() );
continue;
}

length -= recv_now;
}

if( !Running )
break;
//далее обработка пакета
...
}
« Последнее редактирование: 02-12-2007 14:17 от Алексей1153++ » Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #8 : 19-10-2004 07:34 » 

Цитата: lapulya
Mike_mvk, да кто ж так данные принимает...
Цитата
Код:
while( Running )
  {
      nParam = sizeof( SOCKADDR_IN );
      if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )
      {
         TRACE( WSAGetLastError() );
         continue;
      }
   if( !Running )
      break;
//далее обработка пакета
...
надо типа такого
Код:
while( Running )
{
nParam = sizeof( SOCKADDR_IN );
int length = sizeof( PACKET );
char * buffer = (char *) &bp;
while (length > 0)
{
int recv_now = recvfrom( sock, buffer + length, length, 0, &addr, &nParam );
if (recv_now == SOCKET_ERROR )
{
TRACE( WSAGetLastError() );
continue;
}

length -= recv_now;
}

if( !Running )
break;
//далее обработка пакета
...
}



Помимо основной информации, в потоке идет служебная информация, которую надо отфильтровать и обработать. Да к тому же данные идут асинхронно и постоянно. Придется организовывать кольцевой буфер или что-нить еще. Такой алгоритм не пойдет. У меня склейка идет несколько другим образом.

Хотя... Мысль интересная... можно что-ниьт типа такого попробовать...
« Последнее редактирование: 02-12-2007 14:19 от Алексей1153++ » Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #9 : 19-10-2004 07:38 » 

Виноватая я... вот так
Код:
{
nParam = sizeof( SOCKADDR_IN );
int full_length = sizeof( PACKET );
int rev_length = 0;
char * buffer = (char *) &bp;
while (rev_length < full_length)
{
int recv_now = recvfrom( sock, buffer + rev_length, full_length - rev_length, 0, &addr, &nParam );
if (recv_now == SOCKET_ERROR )
{
TRACE( WSAGetLastError() );
continue;
}

rev_length += recv_now;
}

if( !Running )
break;
//далее обработка пакета
...
}
« Последнее редактирование: 02-12-2007 14:21 от Алексей1153++ » Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #10 : 19-10-2004 07:42 » 

lapulya, Все равно немножко некорректно...
sizeof( PACKET ) - размер одного пакета.
Да, к тому же, recvfrom не возвращает количество принятых байт (могу и ошибаться).
Но мысль понятна.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #11 : 19-10-2004 07:45 » 

я это к чему писал-то, дело в том, что так
Цитата

if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )

нет гарантии, что ты примешь ВСЕ данные (т.е. что длинна принятых данных составит sizeof( PACKET )), прием должен происходить в цикле!!!! посмотри описание recvfrom, она возвращает количестко принятых байтов!!!!  :arrow: принимать надо до тех пор пока мы не выберем данных объемом в sizeof( PACKET )

а ты как раз полагаешься на то что твоя разовая операция выберет ВЕСЬ объем!!! отсюда как раз и "потеря данных"
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #12 : 19-10-2004 07:49 » 

lapulya, Я не полагаюсь на то, что разовая операция выберет весь объем. Я выбираю по одному пакету. Разве буфер сокета не сохранит для меня остальные (не выбранные мной) данные?
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #13 : 19-10-2004 07:55 » 

буфер то сохранит (не волнуйся), но повторяю, вызов
Код:
recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam )
не гарантирует того, что в твой bp запишутся данные размером sizeof( PACKET )

ну чисто к примеру, пусть sizeof( PACKET ) равен 10 байтам, после вызова recvfrom ты считаешь что в bp записано (из буфера UDP) ровно 10 байтов, А ЭТО НЕ ВЕРНО, может запросто так случиться что их записано только 3(например)
« Последнее редактирование: 02-12-2007 14:24 от Алексей1153++ » Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #14 : 19-10-2004 08:02 » 

Вот смотри так может понятнее будет

For stream oriented sockets such as those of type SOCK_STREAM, a call to recvfrom returns as much information as is currently available—up to the size of the buffer supplied.
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #15 : 19-10-2004 08:03 » 

lapulya,  Если записано 3, то и прочитаю 3.
Вообще, я что-то запутался...
Поправьте меня, если я скажу что не так.
recvfrom возвращает кол-во прочитанных из буфера сокета данных.
Если данных меньше - прочитает сколько есть.
Если данных нет вообще, то будет ждать.
Если данных больше, чем я прошу прочитать, данные останутся в буфере до след. чтения.

Т.е. теоретически, я могу терять данные только если переполню буфер сокета?
Записан
Mike_mvk
Гость
« Ответ #16 : 19-10-2004 08:04 » 

Цитата: lapulya
Вот смотри так может понятнее будет

For stream oriented sockets such as those of type SOCK_STREAM, a call to recvfrom returns as much information as is currently available—up to the size of the buffer supplied.

У меня так
Код:
 sock = WSASocket( AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, 0, WSA_FLAG_OVERLAPPED );
« Последнее редактирование: 02-12-2007 14:27 от Алексей1153++ » Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #17 : 19-10-2004 08:11 » 

Mike_mvk, вот смотри тыже сам говоришь
Цитата

Если данных меньше - прочитает сколько есть.

а в твоем коде цитирую его
Цитата

while( Running )
  {
      nParam = sizeof( SOCKADDR_IN );
      if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )
      {
         TRACE( WSAGetLastError() );
         continue;
      }
   if( !Running )
      break;
//далее обработка пакета
...

ты никак не сможешь понять что ты принял ТОЛЬКО (допустим) 3 байта при sizeof( PACKET ) равном 10, ты (твой код думает что он считал их буфера UDP ровно sizeof( PACKET ) байтов, тоесть 10, а это НЕ так.... потому что их там было только 3, вот ты 3 и считал)

P.S.
все что ты написал
Цитата

Если данных меньше - прочитает сколько есть.
Если данных нет вообще, то будет ждать.
Если данных больше, чем я прошу прочитать, данные останутся в буфере до след. чтения.

абсолютно верно Ага
Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #18 : 19-10-2004 08:24 » 

:oops:  :oops:  :oops: елы палы........ тут же UDP (во до чего доводит только 6 часов сна в сутки)..... говорю одно думаю про другое....

коли сокет SOCK_DGRAM, то так как ты принимать данные можно, т.е.
Код:
while( Running )
{
nParam = sizeof( SOCKADDR_IN );
if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )
{
TRACE( WSAGetLastError() );
continue;
}
if( !Running )
break;
//далее обработка пакета
...

корректно (прошу прощения) в твоем случае MSDN говорит следующее

For message-oriented sockets, data is extracted from the first enqueued message, up to the size of the buffer supplied. If the datagram or message is larger than the buffer supplied, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost.

так что виноватая я, буду читать чего люди спрашивают повнимательнее
« Последнее редактирование: 02-12-2007 14:29 от Алексей1153++ » Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #19 : 19-10-2004 08:33 » 

а вот
TRACE( WSAGetLastError() );
ничего не пишет... например WSAEMSGSIZE
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #20 : 19-10-2004 08:58 » 

Цитата: lapulya
а вот
TRACE( WSAGetLastError() );
ничего не пишет... например WSAEMSGSIZE


Это у меня макрос такой.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #21 : 19-10-2004 09:11 » 

я понял что макрос.... Отлично  я имел ввиду, не дает ли ошибок recvfrom при вызове, особенно эту WSAEMSGSIZE
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #22 : 19-10-2004 09:21 » 

lapulya, Ошибок нет. SOCKET_ERROR не возникает.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #23 : 19-10-2004 09:33 » 

для верности  Улыбаюсь  я бы все же проверил количество принятых байтов т.е. написал бы так
Код:
int result = recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam );
if ((result == SOCKET_ERROR) || (result != sizeof( PACKET )))
{
   TRACE( WSAGetLastError() );
   continue;
}
« Последнее редактирование: 02-12-2007 14:31 от Алексей1153++ » Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #24 : 19-10-2004 09:41 » 

lapulya, Именно так и пробовал. Результат: пропадания есть, но на TRACE не попадает.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #25 : 19-10-2004 10:03 » 

я не совсем понял твой пост, так всегда ли result ==sizeof( PACKET ) или нет, т.е. равны ли следующее выражения в любых проводимых тобой тестах
1. recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam )
2. sizeof( PACKET )
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #26 : 19-10-2004 10:09 » 

Цитата: lapulya
я не совсем понял твой пост, так всегда ли result ==sizeof( PACKET ) или нет, т.е. равны ли следующее выражения в любых проводимых тобой тестах
1. recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam )
2. sizeof( PACKET )


Да, равны. recvfrom всегда возвращает значение равное  sizeof( PACKET ).
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #27 : 19-10-2004 10:44 » 

мдаааа..... нельзя ли для чистоты эксперимента сменить порт с 100 на что нить другое...
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #28 : 19-10-2004 10:50 » 

Цитата: lapulya
мдаааа..... нельзя ли для чистоты эксперимента сменить порт с 100 на что нить другое...
Можно, но сложно... Девайс перепрограммировать надо... Однако похоже это единственное, что осталось попробовать.
Буду пробовать...
О результатах доложу.
Записан
Mike_mvk
Гость
« Ответ #29 : 19-10-2004 10:58 » 

Смена порта на 10000 не помогла. Сбои продолжаются, к сожалению...

Возник вопрос: а может ли каким-либо образом обмен по одному сокету влиять на обмен по другому сокету?
Записан
Mike_mvk
Гость
« Ответ #30 : 19-10-2004 11:20 » 

Столкнулся с интересной штукой.
На сокет идут датаграммы с полем данных размеров 138 байт.
При использовании recvfrom с размером данных в 10 (в общем-то это не важно, можно и меньше) раз большим размером данных:
Код:
int result = recvfrom( sock, (char *) &bp, sizeof( PACKET ) * 10, 0, &addr, &nParam );

result = 160!
Что за фигня?

И еще.
Провел опыт. В While перед recvfrom поставил Sleep. Т.е. принудительно заставил поток тормозить. Буфер с этим справляется. Данные что попали в сокет считались программой (забавно было: поток по линии связи остановился, а программа все принимала пакеты).

Однако, что странно. Уже внутри буфера обнаруживалось отсутствие некоторых пакетов.
« Последнее редактирование: 02-12-2007 14:32 от Алексей1153++ » Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #31 : 19-10-2004 12:20 » 

ну а если сокет открывать не так
Код:
sock = WSASocket( AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, 0, WSA_FLAG_OVERLAPPED );
а так
Код:
sock = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_UDP, 0, 0, WSA_FLAG_OVERLAPPED );

и вместо этого
Код:
nParam = sizeof( SOCKADDR_IN );
if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )
{
TRACE( WSAGetLastError() );
continue;
}
это
Код:
  nParam = sizeof( SOCKADDR_IN );
   int full_length = sizeof( PACKET );
   int rev_length = 0;
   char * buffer = (char *) &bp;
   while (rev_length < full_length)
   {
      int recv_now = recvfrom( sock, buffer + rev_length, full_length - rev_length, 0, &addr, &nParam );
      if (recv_now == SOCKET_ERROR )
      {
         TRACE( WSAGetLastError() );
         continue;
      }

      rev_length += recv_now;
   }
« Последнее редактирование: 02-12-2007 14:35 от Алексей1153++ » Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #32 : 19-10-2004 12:27 » 

lapulya,  SOCK_STREAM не получится. Это уже будет TCP. Я бы с удовольствием перешел на TCP, но девайс не позволяет организовать полноценную поддержку этого протокола ( как я уже говорил, даже ARP ему не по силам).
Записан
Diletant
Помогающий

de
Offline Offline

« Ответ #33 : 19-10-2004 12:36 » 

Никогда не использовал recvfrom, поэтому извиняюсь за возможную дикость. Но... Сокет объявлен с флагом  WSA_FLAG_OVERLAPPED, стандартный recv в данном случае не должен вообще дожидаться ни единого байта, а занесение данных происходит по событию.  В описании recvfrom  стоит , что правила блокировки у обеих функций одинаковы. Вывод: попробуй убрать флаг.

Если ты заказываешь считывать 100 байт, а в данный момент придет пакет размером в 101, то 1 байт потеряется, не зависимо от того, что в следующие пять минут не придет ни одного байта. Вывод 2: Проверь размер пакета выплевываемого девайсом.

Есть куча программ, слушающая протокол IP. На исходниках.ру даже валялся иходник. Посмотори, что творится в твоей сети.
Записан
Mike_mvk
Гость
« Ответ #34 : 19-10-2004 12:55 » 

Цитата
Вывод: попробуй убрать флаг.
С флагом или без - ничего не меняется.
Цитата
Если ты заказываешь считывать 100 байт, а в данный момент придет пакет размером в 101, то 1 байт потеряется, не зависимо от того, что в следующие пять минут не придет ни одного байта. Вывод 2: Проверь размер пакета выплевываемого девайсом.

Есть куча программ, слушающая протокол IP. На исходниках.ру даже валялся иходник. Посмотори, что творится в твоей сети.

Я пользуюсь Ethereal'ом.

Вот такой пакет формируется:

Код:
Ethernet Header
Source MAC      11:11:11:11:11:11 (Multicast)
Dest MAC        FF:FF:FF:FF:FF:FF (Broadcast)
Protocol type   0x0800 (IP)
IP Header
Version         4
Header length   20
Service type    0x00
Total length    166
Fragment ID     0x0000
Flags           0x0000
Fragment offset 0
Time to live    128 seconds/hops
Protocol type   0x11 (UDP)
Checksum        0x3A48
Source address  0.0.0.0
Dest address    255.255.255.255
UDP Header
Source port     512 (EXEC)
Dest port       100 (0NEWACCT)
Message length  146
Checksum        0x0000

Message length  146 = 138 DATA + 8 UDP Header

Вроде все честно.
« Последнее редактирование: 02-12-2007 14:36 от Алексей1153++ » Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #35 : 19-10-2004 13:01 » 

Mike_mvk, Mike_mvk, флаг SOCK_STREAM ничего о протоколе не говорит, протокол определяется флагом IPPROTO_UDP (для TCP значение флага должно быть IPPROTO_TCP)
Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #36 : 19-10-2004 13:04 » 

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

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #37 : 19-10-2004 13:17 » 

Diletant,
Цитата

Если ты заказываешь считывать 100 байт, а в данный момент придет пакет размером в 101, то 1 байт потеряется, не зависимо от того, что в следующие пять минут не придет ни одного байта.

наколько я понял предполагается что все пакеты одинакового размера... или я не прав???
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #38 : 19-10-2004 13:20 » 

lapulya, все пакеты одинаковые по размеру.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #39 : 19-10-2004 14:10 » 

Mike_mvk, sizeof( PACKET ) чему равен
Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #40 : 19-10-2004 14:25 » 

lapulya, sizeof( PACKET ) = 138
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #41 : 19-10-2004 14:43 » 

мдааааа тогда вот это
Цитата

При использовании recvfrom с размером данных в 10 (в общем-то это не важно, можно и меньше) раз большим размером данных:
Код:

int result = recvfrom( sock, (char *) &bp, sizeof( PACKET ) * 10, 0, &addr, &nParam );

result = 160!
Что за фигня?

оооочень странно...

ребилд олл + рестарт ОС
Записан

С уважением Lapulya
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #42 : 19-10-2004 16:08 » 

Mike_mvk, посмотри в нескольких пакетах значение поля checksum заголовка UDP.  Меня сильно смущает  то, что checksum=0.

По RFC поле checksum не может быть 0, если вычисленная сумма равна 0, то в поле checksum заносится 0xffff

Цитата

If the computed  checksum  is zero,  it is transmitted  as all ones (the
equivalent  in one's complement  arithmetic).   An all zero  transmitted
checksum  value means that the transmitter  generated  no checksum  (for debugging or for higher level protocols that don't care).


Возможно, что реализация WinSock отбрасывает пакеты с контрольной суммой = 0.

Закинь распечатку пакета, который точно не был получен.  Может с ним что не в порядке.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Mike_mvk
Гость
« Ответ #43 : 20-10-2004 06:05 » 

По тому же RFC написано, что поле контрольной суммы может быть нулевым. Это используется для отладки.
Цитата
An all zero transmitted
checksum value means that the transmitter generated no checksum (for debugging or for higher level protocols that don't care).

Winsock ( как и большинство других ) принимает такие пакеты.
Дело в том, что мой девайс использует заранее прописанные заголовки пакетов (из-за малой производительности не было возможности формировать заголовок пакета динамически, да к тому же вычислять КС). Поэтому все пакеты имеют абсолютно одинаковые заголовки. Меняются только данные.
По-моему, проблема совсем не в КС.
Еще раз повторюсь: пакеты начинают пропадать когда начинается обмен по другим сокетам.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #44 : 20-10-2004 08:47 » 

может ошибка как-то связана с обработкой пакетов, давай попробуем локализовать ошибку, сделай прием данных без обработки т.е. таким
Код:
int numberOfPackets = 0;
while (1)
{
nParam = sizeof( SOCKADDR_IN );
int length = recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam );
if ((length == SOCKET_ERROR) || (length != sizeof( PACKET )))
{
//   ЖОПА!!!
TRACE( WSAGetLastError() );
continue;
}

numberOfPackets++;
}
т.е. чисто для того, чтобы поглядеть на количество пакетов...

нусть устройство пошлет ну там 50 пакетов, а мы в отладчике поглядим сколько прога приняла
« Последнее редактирование: 02-12-2007 14:42 от Алексей1153++ » Записан

С уважением Lapulya
Mike_mvk
Гость
« Ответ #45 : 20-10-2004 10:22 » 

Я делал так:
заставил девайс в данных слать мне байтом циклический счетчик (т.е. номер пакета). После recvfrom писал содержимое этого байта в лог. Входящие пакеты также перехватывались ethereal'ом.
Результат:
То что перехватил ethereal - счетчик идет нормально, т.е. пакеты до сетевой доходят. Однако, в логе программы счетчик пакетов сбивается, т.е. из recvfrom некоторые пакеты не выходят.
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #46 : 20-10-2004 16:24 » 

Mike_mvk, дурацкое предложение: заменить все вызовы WSA функций на BSD функции.  Например, WSASocket -> socket.  Вдруг что-то измениться.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Mike_mvk
Гость
« Ответ #47 : 21-10-2004 06:48 » 

Я хочу попробовать немножко другое решение. В связи с этим у меня куча вопросов.

Вопрос номер раз. Чисто теоритически возможна ли такая ситуация: сокеты, находящиеся в разных потоках в программе, мешают друг другу находясь в ожидании. Т.е. один сокет ждет в recv, другой перешел в send (или recv) и первый при этом пропустил пакет.

Вопрос намбер ту. Возможно ли разрешить мою ситуевину с помощью такого зверя, как WSAEVENT? Я уже кое что попробовал с ним. И уже в связи с этим

Вопрос номер три.

Код:
...
WSAEVENT hEvent1;
...

if( WSAStartup ( MAKEWORD( 2, 2 ), &wsaData ) != 0 )
  return TRACE( WSAGetLastError() );
sock = WSASocket( AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, 0, 0 );
if( sock == INVALID_SOCKET )
  return TRACE( WSAGetLastError() );

addr.sin_family = AF_INET ;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(100);

if( bind( sock, (LPSOCKADDR) &addr, sizeof( addr ) ) != 0 )
  return TRACE( WSAGetLastError() );

hEvent1 = WSACreateEvent();

WSAEventSelect( sock, hEvent1, FD_READ);

while( Running )
{

  WSAWaitForMultipleEvents( 1, &hEvent1, TRUE, WSA_INFINITE, FALSE );
  nParam = sizeof( SOCKADDR_IN );
  if( recvfrom( sock, (char *) &bp, sizeof( PACKET ), 0, &addr, &nParam ) == SOCKET_ERROR )
{
                                   return TRACE( WSAGetLastError() );
   continue;
}
...
//Дальнейшая обработка пакета.

Это кусок периодически вываливается с WSAWOULDBLOCK. Почему?

ps Буду признателен за любые идеи.
« Последнее редактирование: 02-12-2007 14:43 от Алексей1153++ » Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #48 : 21-10-2004 09:39 » 

Цитата

Вопрос номер раз. Чисто теоритически возможна ли такая ситуация: сокеты, находящиеся в разных потоках в программе, мешают друг другу находясь в ожидании. Т.е. один сокет ждет в recv, другой перешел в send (или recv) и первый при этом пропустил пакет.

они же на разных портах, поэтому такого быть не должно (если такое произойдет то просто нужно пойти и набить морду тому кто писал стек... Отлично )
Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #49 : 14-01-2009 10:02 » 

Mike_mvk, Привет решилась ли проблема? Если да, то в чем она была? Кстати еще мысль, о которой мы тут не поговорили... может твоя прога где то в другом месте (так сказать под покровом ночи) читает данные из принятого буфера, а ты просто об этом не знаешь, вот тебе и пропажа пакетов, это я бы сказал наиболее вероятная причина (короче, кто-то, когда-то ворует данные из твоего буфера, а не они сами пропадают)

Я почему сюда зашел, просто тут в другой теме обсуждаем про прием "пакетов" данных от сервера... и я искал пример где я уже об этом говорил
Записан

С уважением Lapulya
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #50 : 14-01-2009 17:23 » 

lapulya, Эээээ тема как уже почти 5 лет не поднималась.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #51 : 14-01-2009 17:27 » 

Finch, Да я вижу, но вот наткнулся, когда сегодня про сокеты разговаривали (точнее когда я сказал, что уже описывал решение проблемы и неоднократно) и спросил... Мне интересно как решился вопрос, если товарищ ходит на сайт может и ответит.

И не почти 5 лет, а только почти 4 года Ага
Записан

С уважением Lapulya
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #52 : 14-01-2009 20:51 » 

lapulya, он давно уже "гость".
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: 1 2 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines