| 
			| 
					
						| 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 
								Молодой специалист    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 
								Помогающий    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 HeaderSource 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 
								Молодой специалист    Offline | 
								|  | « Ответ #35 : 19-10-2004 13:01 »  |  | 
 
 Mike_mvk, Mike_mvk, флаг SOCK_STREAM ничего о протоколе не говорит, протокол определяется флагом IPPROTO_UDP (для TCP значение флага должно быть IPPROTO_TCP) |  
						| 
								|  |  
								|  |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    Offline | 
								|  | « Ответ #36 : 19-10-2004 13:04 »  |  | 
 
 хотя....... тут ведь целый пакет пропадает, а не часть его..... наврятли это поможет.... ща еще подумаю |  
						| 
								|  |  
								|  |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    Offline | 
								|  | « Ответ #37 : 19-10-2004 13:17 »  |  | 
 
 Diletant,  Если ты заказываешь считывать 100 байт, а в данный момент придет пакет размером в 101, то 1 байт потеряется, не зависимо от того, что в следующие пять минут не придет ни одного байта.
 
 наколько я понял предполагается что все пакеты одинакового размера... или я не прав??? |  
						| 
								|  |  
								|  |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| Mike_mvk 
								Гость
 | 
								|  | « Ответ #38 : 19-10-2004 13:20 »  |  | 
 
 lapulya, все пакеты одинаковые по размеру. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    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 
								Молодой специалист    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 | 
								|  | « Ответ #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. Закинь распечатку пакета, который точно не был получен.  Может с ним что не в порядке. |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| 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 
								Молодой специалист    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 | 
								|  | « Ответ #46 : 20-10-2004 16:24 »  |  | 
 
 Mike_mvk, дурацкое предложение: заменить все вызовы WSA функций на BSD функции.  Например, WSASocket -> socket.  Вдруг что-то измениться. |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| 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 
								Молодой специалист    Offline | 
								|  | « Ответ #48 : 21-10-2004 09:39 »  |  | 
 
 Вопрос номер раз. Чисто теоритически возможна ли такая ситуация: сокеты, находящиеся в разных потоках в программе, мешают друг другу находясь в ожидании. Т.е. один сокет ждет в recv, другой перешел в send (или recv) и первый при этом пропустил пакет.
 
 они же на разных портах, поэтому такого быть не должно (если такое произойдет то просто нужно пойти и набить морду тому кто писал стек...    ) |  
						| 
								|  |  
								|  |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    Offline | 
								|  | « Ответ #49 : 14-01-2009 10:02 »  |  | 
 
 Mike_mvk, Привет решилась ли проблема? Если да, то в чем она была? Кстати еще мысль, о которой мы тут не поговорили... может твоя прога где то в другом месте (так сказать под покровом ночи) читает данные из принятого буфера, а ты просто об этом не знаешь, вот тебе и пропажа пакетов, это я бы сказал наиболее вероятная причина (короче, кто-то, когда-то ворует данные из твоего буфера, а не они сами пропадают)
 Я почему сюда зашел, просто тут в другой теме обсуждаем про прием "пакетов" данных от сервера... и я искал пример где я уже об этом говорил
 |  
						| 
								|  |  
								|  |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #50 : 14-01-2009 17:23 »  |  | 
 
 lapulya, Эээээ тема как уже почти 5 лет не поднималась. |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| lapulya 
								Молодой специалист    Offline | 
								|  | « Ответ #51 : 14-01-2009 17:27 »  |  | 
 
 Finch, Да я вижу, но вот наткнулся, когда сегодня про сокеты разговаривали (точнее когда я сказал, что уже описывал решение проблемы и неоднократно) и спросил... Мне интересно как решился вопрос, если товарищ ходит на сайт может и ответит. И не почти 5 лет, а только почти 4 года   |  
						| 
								|  |  
								|  |  Записан | 
 
 С уважением Lapulya |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #52 :  14-01-2009 20:51 »   |  | 
 
 lapulya, он давно уже "гость". |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	|  |