Пакеты иногда не приходят на сокет
От: Ux  
Дата: 29.11.07 09:01
Оценка:
Visual Studio 2005, pure C, GTK

Идёт активный опрос (вопрос-ответ) удалённой системы. Периодически не приходят целые цепочки (Прогресс роста ~ 1, 5, 50, 100, ...) ответов, хотя снифер видит соответствующие пакеты. Чем дольше программа работает, тем больше эти "провалы". За семь минут 200 пакетов.

Функция считывания пакетов.

int tcp_receive_ind(SOCKET socket, unsigned char* buf, int len)
{
    fd_set fds, fds_ex;
    struct timeval timeout;
    int delay;
    int res;
    DWORD dt = 0;

    FD_ZERO (&fds);
    FD_SET (socket, &fds);
    FD_ZERO (&fds_ex);
    FD_SET (socket, &fds_ex);
        
    timeout.tv_sec = 0;
    delay = 150000;//microseconds
    timeout.tv_usec = delay;
    
    dt = GetTickCount();
    if((res = select(socket, &fds, NULL, &fds_ex, &timeout)) <= 0)
    {
        if (res == 0)
        {
            static int cnt = 0;
            dt = GetTickCount() - dt;
            printf("timeout N %d, dt = %d ms\n", cnt++, dt);        
        }
        else
        {
            printf("Select FAULT!\n");        
        }    
        return 0;
    }
            
    if (FD_ISSET (socket, &fds))
    {                       
        if (((res=recv(socket, buf, len, 0))==0)||((res==SOCKET_ERROR)&&(WSAGetLastError()==WSAECONNRESET)))
        {
            printf("May be disconnect!\n");            
            return -1;
        }        
        return res;            
    }
    else
    {        
        return 0;
    }    
}



29.11.07 18:52: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
Re: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 29.11.07 09:24
Оценка:
За 5 минут и 3160 пакетов 78 таймаутов.
Re: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 29.11.07 09:42
Оценка:
В цепочках идёт чёткое чередование: таймаут, ответ, таймаут, ответ, таймаут, ...
Re: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 29.11.07 11:40
Оценка:
Первый таймаут на 256-м пакете
Далее:
513 515
771 773 775
1030 1032 1034 1036
1290 1292 1294 1296 1298
ну и так далее
Re: Пакеты иногда не приходят на сокет
От: TarasCo  
Дата: 29.11.07 17:12
Оценка:
Я чего то не пойму, Вы TCP используете? Или присоединенный UDP сокет? В первом случае ни о каких пакетах речь не может идти — транспортный драйвер собирает поток как ему заблагорассудится — может по байту отдавать, а может и по 10 кб — величина в общем случае не связана с размером пакета, переданного через сеть ( хотя естественно корреляция наблюдается обычно ). Если это UDP сокет — то при активном обмене может просто переполняться буфер драйвера, он не будет для вас там тыщщи пакетов хранить.
Да пребудет с тобою сила
Re[2]: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 30.11.07 08:25
Оценка:
Вообще то ТСР (в имени функции присутствует).
Режим вопрос-ответ. Пакеты просто не могут переполнять буфер, поскольку приходят по одному.
Снифер их все видит.
И не понятно откуда берётся закономерность:
256-й
513, 515
771, 773, 775
1030, 1032, 1034, 1036
и т.д.
Re[3]: Пакеты иногда не приходят на сокет
От: TarasCo  
Дата: 30.11.07 09:42
Оценка:
Ux>Вообще то ТСР (в имени функции присутствует).

Если Вы работаете с TCP, то не стоит искать соответствия между получаемыми данными через ф. recv и принятыми пакетами. Т.е вы видите сниффером, что пришло 10 пакетов по протоколу TCP. Если Вы при этом в цикле вызываете recv — она может сработать от 0 до 10 раз ( а может и больше — зависит от размера буфера ). Если у Вас теряются данные — ищите ошибку в коде.

Ux>И не понятно откуда берётся закономерность:

Ux>256-й
Ux>513, 515
Ux>771, 773, 775
Ux>1030, 1032, 1034, 1036
Ux>и т.д.
А закономерностей искать не надо — этак можно до дурки дойти.
Да пребудет с тобою сила
Re[4]: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 30.11.07 10:13
Оценка:
Здравствуйте, TarasCo, Вы писали:

TC>Если Вы работаете с TCP, то не стоит искать соответствия между получаемыми данными через ф. recv и принятыми пакетами.


Прийти должен только один пакет. И он приходит, но из сокета вычитать я его не могу. И не получаю каждый 256-й с ростом непринятых на один с чередованием через один.

TC>А закономерностей искать не надо — этак можно до дурки дойти.


Если бы она не повторялась на других компах. И в других компиляторах. В Висуал 6.0 та же фигня.
Re[5]: Пакеты иногда не приходят на сокет
От: Michael Chelnokov Украина  
Дата: 30.11.07 11:12
Оценка:
Здравствуйте, Ux, Вы писали:

Ux>Прийти должен только один пакет. И он приходит, но из сокета вычитать я его не могу.


Всё ты можешь, только зачем-то наворотил селектов с таймаутами (кстати, и даже после "неудачного" селекта ты всё равно можешь спокойно прочитать данные).

Ux>И не получаю каждый 256-й с ростом непринятых на один с чередованием через один.


Тебе уже объяснили два раза, почему это происходит.

Ux>Если бы она не повторялась на других компах. И в других компиляторах. В Висуал 6.0 та же фигня.


Причем тут компиляторы? Скажу тебе страшную тайну — точно такую же картину ты бы увидел и на Delphi и на C# и на Java
Re[6]: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 30.11.07 11:47
Оценка:
Здравствуйте, Michael Chelnokov, Вы писали:

MC>Всё ты можешь, только зачем-то наворотил селектов с таймаутами (кстати, и даже после "неудачного" селекта ты всё равно можешь спокойно прочитать данные).


Иначе просто клинит программу на этом самом 256-м чтении. Прочитать данные соответственно не могу.

MC>Тебе уже объяснили два раза, почему это происходит.


Не объяснили.
Я всегда получаю целые пакеты.
75 байт данных, хотя буфер для ресива несколько больше.
Следующее обращение получает удачный ответ.
А через одно опять ошибка.
При этом более одного пакета данных за раз я не получаю.

Клиентская часть проверялась на двух компьютерах. Драйвера сетевых карт соответственно разные.

Возжность присутствия ошибки я признаю, но её найти не могу.

MC>Причем тут компиляторы? Скажу тебе страшную тайну — точно такую же картину ты бы увидел и на Delphi и на C# и на Java


Я не был бы столь категоричен.

П.С. Я просто хотел "услышать" мнение человека, который с таким сталкивался.
Re[7]: Пакеты иногда не приходят на сокет
От: Michael Chelnokov Украина  
Дата: 30.11.07 13:47
Оценка:
Здравствуйте, Ux, Вы писали:

Ux>Иначе просто клинит программу на этом самом 256-м чтении.


Ладно, начнем сначала. Зачем тебе там вообще потребовался select с таймаутом?
Re[8]: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 30.11.07 13:58
Оценка:
MC>Ладно, начнем сначала. Зачем тебе там вообще потребовался select с таймаутом?
Для проверки наличия данных для чтения в сокете.

А что что-то не так?
Re[9]: Пакеты иногда не приходят на сокет
От: Michael Chelnokov Украина  
Дата: 30.11.07 14:03
Оценка:
Здравствуйте, Ux, Вы писали:

MC>>Ладно, начнем сначала. Зачем тебе там вообще потребовался select с таймаутом?

Ux>Для проверки наличия данных для чтения в сокете.

Зачем это тебе нужно? recv все равно вернет данные.

Ux>А что что-то не так?


Да все так, только ты почему-то удивляешься получению результата, ради которого и наворачивал весь этот код с select и таймаутом. Если бы твоя функция была из одной строчки (вызова recv), то у тебя бы не возникло вопросов.
Re[10]: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 30.11.07 14:37
Оценка:
MC>Зачем это тебе нужно? recv все равно вернет данные.
Не вернёт, если не было дисконекта, сокет блокируемый и пакет не пришёл. И будет тупо ждать данных.

Сделал одним ресивом с включеной опцией таймаута. Та же прогрессия пропадания пакетов.
Re[11]: Пакеты иногда не приходят на сокет
От: Michael Chelnokov Украина  
Дата: 30.11.07 14:41
Оценка:
Здравствуйте, Ux, Вы писали:

MC>>Зачем это тебе нужно? recv все равно вернет данные.

Ux>Не вернёт, если не было дисконекта, сокет блокируемый и пакет не пришёл. И будет тупо ждать данных.

Пусть ждет. Нет данных — ждет, появятся — вернет. Пропадет передатчик — recv отвалится по таймауту сам, расценивай это как disconnect.
Re[12]: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 30.11.07 14:52
Оценка:
MC>Пусть ждет. Нет данных — ждет, появятся — вернет. Пропадет передатчик — recv отвалится по таймауту сам, расценивай это как disconnect.

1. А я думал, что дисконнект проверяется по возврату нуля от этой функции.
2. Мне что писать отдельный поток для приёма данных из сокета? А потом их синхронизировать?
3. Почему ни кого не удивляет наличие подобной прогрессии по пропаданию пакетов? На 256-м пакете прогу обязательно заклинит, а это 21-я секунда работы системы. Не помогает даже дисконнект и открытие новой сессии.
Re[13]: Пакеты иногда не приходят на сокет
От: Michael Chelnokov Украина  
Дата: 30.11.07 15:08
Оценка:
Здравствуйте, Ux, Вы писали:

MC>>Пусть ждет. Нет данных — ждет, появятся — вернет. Пропадет передатчик — recv отвалится по таймауту сам, расценивай это как disconnect.


Ux>1. А я думал, что дисконнект проверяется по возврату нуля от этой функции.


0 — другая сторона говорит что больше данных не будет. По соединению все еще можно передавать данные с твоей стороны.
-1 — ошибка, под виндой смело можешь считать что соединение сдохло.

Ux>2. Мне что писать отдельный поток для приёма данных из сокета? А потом их синхронизировать?


Нафига?

Ux>3. Почему ни кого не удивляет наличие подобной прогрессии по пропаданию пакетов?


Я уже устал повторять что никакого пропадания не происходит, дело в твоем коде с select и таймаутом.

А никого это не удивляет, поскольку так работает TCP. Для повышения скорости передачи данных TCP пытается обьединить как можно больше порций данных в один сегмент. Описание можешь почитать здесь. Отключается на стороне передатчика установкой опции TCP_NODELAY.
Re[14]: Пакеты иногда не приходят на сокет
От: Ux  
Дата: 30.11.07 15:35
Оценка:
MC>0 — другая сторона говорит что больше данных не будет. По соединению все еще можно передавать данные с твоей стороны.
MC>-1 — ошибка, под виндой смело можешь считать что соединение сдохло.

If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

MC>А никого это не удивляет, поскольку так работает TCP. Для повышения скорости передачи данных TCP пытается обьединить как можно больше порций данных в один сегмент.


Ну не объединяет он. В дампе снифера нормальные Езернет фреймы с одиночными пакетами. Всё в порядке вопрос-ответ.
Re[15]: Пакеты иногда не приходят на сокет
От: Michael Chelnokov Украина  
Дата: 30.11.07 16:01
Оценка:
Здравствуйте, Ux, Вы писали:

MC>>0 — другая сторона говорит что больше данных не будет. По соединению все еще можно передавать данные с твоей стороны.

MC>>-1 — ошибка, под виндой смело можешь считать что соединение сдохло.

Ux>If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.


И где отличия от того что я написал?
Слушай, я уже 10 лет этим кормлюсь. Неужели ты думаешь что данный текст мне неизвестен? Да я его наизусть знаю, как букварь.

MC>>А никого это не удивляет, поскольку так работает TCP. Для повышения скорости передачи данных TCP пытается обьединить как можно больше порций данных в один сегмент.


Ux>Ну не объединяет он. В дампе снифера нормальные Езернет фреймы с одиночными пакетами. Всё в порядке вопрос-ответ.


Опять "пакеты" в TCP...
Я устал. RTFM.
Re[15]: Пакеты иногда не приходят на сокет
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 30.11.07 16:18
Оценка:
Здравствуйте, Ux, Вы писали:

Ux>Ну не объединяет он.


"сейчас не объединяет и не разделяет" и "никогда не будет объединять или разделять" — две большие разницы
... << RSDN@Home 1.2.0 alpha rev. 780>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.