The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
" объединение отсылаемых пакетов"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

" объединение отсылаемых пакетов" 
Сообщение от kowak emailИскать по авторуВ закладки(ok) on 15-Сен-05, 17:39  (MSK)
Есть Сервер и Клиент на неблокирующих сокетах
Клиент:
...
send(sock, str1, len1, 0);
send(sock, str2, len2, 0);

Сервер:
...
Sleep(5000);
read_data = recv(sock, str, BUF_SIZE, 0);

При одновременном запуске, Сервер получит read_data==len1+len2 (если len1+len2<=FUB_SIZE),
а нужно чтобы read_data==len1;
Вобщем, чтобы пакеты не объединялись.

  Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. " объединение отсылаемых пакетов" 
Сообщение от Alexander S. Salieff emailИскать по авторуВ закладки on 15-Сен-05, 20:48  (MSK)
>Есть Сервер и Клиент на неблокирующих сокетах
>Клиент:
>...
>send(sock, str1, len1, 0);
>send(sock, str2, len2, 0);
>
>Сервер:
>...
>Sleep(5000);
>read_data = recv(sock, str, BUF_SIZE, 0);
>
>При одновременном запуске, Сервер получит read_data==len1+len2 (если len1+len2<=FUB_SIZE),
>а нужно чтобы read_data==len1;
>Вобщем, чтобы пакеты не объединялись.

Если это TCP то они могут не только объединяться, но и разъединяться на сегменты любой длины. Любой сильно интеллектуальный роутер (или стек ОСи) может склеить несколько пакетов  в кучку или разбить один пакет на части. Это же поточный протокол, он не обязан согранять границы дейтаграмм. Если тебе не важна гарантия доставки, юзай UDP, он датаграмм-ориентированный. Или расширяй протокол передачи, чтобы каждому блоку данных соответствовал заголовок, в котором указана длина блока.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

2. " объединение отсылаемых пакетов" 
Сообщение от serge emailИскать по авторуВ закладки(??) on 16-Сен-05, 17:51  (MSK)
>Есть Сервер и Клиент на неблокирующих сокетах
>Клиент:
>...
>send(sock, str1, len1, 0);
>send(sock, str2, len2, 0);
>
>Сервер:
>...
>Sleep(5000);
>read_data = recv(sock, str, BUF_SIZE, 0);
>
>При одновременном запуске, Сервер получит read_data==len1+len2 (если len1+len2<=FUB_SIZE),
>а нужно чтобы read_data==len1;
>Вобщем, чтобы пакеты не объединялись.

отключите буферизацию на клиенте.
flags = fcntl(fd, F_GETFL, 0);
rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
но делать так - плохо. )
протокол уровня прилижения работающий поверх TCP не должен быть завязан на размер блока, т.к. TCP - поточный протокол, а не пакетный.
Имейте ввиду, может получиться так, что один send/write() на отправляющей стороне может привратится в два recv/read меньшего размера на принимающей. Это зависит от нагрузки на ядро в этот момент и размера MTU по маршруту пакета.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

3. " объединение отсылаемых пакетов" 
Сообщение от genie Искать по авторуВ закладки on 20-Сен-05, 04:29  (MSK)
Ne sovsem tak - nado otkluchat' Nagle:

int zero=0;
setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(unsigned char *)&zero,sizeof(int));

Hotya eto tol'ko lokal'nyi kontrol' - kak pravil'no zametili, routers mogut eti pakety kombinirovat' po svoemu usmotreniu.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

4. " объединение отсылаемых пакетов" 
Сообщение от serge emailИскать по авторуВ закладки(??) on 20-Сен-05, 04:57  (MSK)
да, сорри. смотрел на один кусок исходника, а скопировал другой.  )
но ведь нам ;-) нужно ВКЛЮЧИТЬ режим TCP_NDELAY, для этого флаг нужно выставить в значение, отличное от 0.
разве не так?
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

5. " объединение отсылаемых пакетов" 
Сообщение от genie Искать по авторуВ закладки on 20-Сен-05, 05:02  (MSK)
Ugu, pral'na...

A esche ya glupost' napisal - ne mogut routers pakety skleivat', poetomu vse eto dobro budet idti, kak ono est'. Bol'shinstvo TCP stacks dlya ertogo PUSH flag ispol'zuut.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

6. " объединение отсылаемых пакетов" 
Сообщение от serge emailИскать по авторуВ закладки(??) on 20-Сен-05, 05:25  (MSK)
Согласен. На промежуточных роутерах пакеты могут только измельчаться из-за нестыковок MTU, а склеиваться могут только в ядре принимающей стороны. И, думаю, только для stream- протоколов, таких как TCP.
По этому - повторюсь. В любом случае, нельзя рассчитывать на размер отправляемого блока данных.
Очевидный совет автору топика.
Принимайте данные как можно бОльшими кусками, в разумных пределах, конечно. )
Это сократит количество syscalls и снизит нагрузку на ядро.
А получив данные, уже можно разобраться всё получено или нет.
Протокол, в простейшем случае, может выглядеть как, например, четыре байта с размером блока + сам блок данных.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

7. " объединение отсылаемых пакетов" 
Сообщение от Hordi emailИскать по авторуВ закладки on 20-Сен-05, 13:16  (MSK)
Абсолютно согласен с serge. Флаг TCP_NDELAY лишь указывает отправлять немедленно и не использовать алгоритм объединения в оптимальные для пересылки куски, но совсем не управляет тем, как данные поступят.
Чем больше за раз из сокета сможешь прочитать тем лучше. А парсингом приходящих данных должна заниматься сама программа.
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

8. " объединение отсылаемых пакетов" 
Сообщение от enot Искать по авторуВ закладки(??) on 21-Сен-05, 14:20  (MSK)
Промежуточное сетевое оборудование (гы кто сказал что только роутеры?) может делать с пакетами все что угодно ;-)) Сам видел.. Знаю, знаю стандарты и все такое.. однако может быть все что угодно. Вот из этого и надо исходить.

1. Поэтому надо отказаться от неблокируемых сокетов - плохая идея.
2. Использовать select/poll
3. Написать функцию оболочку ReceivePack для функции recv()
Пусть получает на вход еще и таймаут.
int ReceivePack(int fd, void *buf, int len, int timeout)
{
  // bla bla bla

  r_len = 0;
  for (int size = 0 ; size < len; size += r_len) {

    select(...) /// timeout

    if (данные мона читать?) {
// ждем блок, если меньше повторим
      r_len = recv(fd, buf, len-size,.....); // ждем блок, если меньше повторим
      if (r_len <0) { /// errors ; return -1; }
      size+=r_len;
    }
  }
  return 0; // прочитан весь блок
}

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

9. " объединение отсылаемых пакетов" 
Сообщение от enot Искать по авторуВ закладки(??) on 21-Сен-05, 14:42  (MSK)
Промежуточное сетевое оборудование (кто сказал что будут только роутеры?) может делать с пакетами все что угодно ;-)) Сам видел.
Знаю, знаю стандарты и все такое.. однако может быть все что угодно. Еще и Оська чудить может (гы, будет). Вот из этого и надо исходить.

1. Поэтому надо отказаться от неблокируемых сокетов - плохая идея.
Это ж непрерывное переключение контекста...
2. Использовать select/poll . Чтоб не висеть если ничего не придет.
3. Написать функцию оболочку ReceivePack для функции recv()
Пусть получает на вход еще и таймаут. И ее использовать для приема пакетов. Сильно схематично:

// Получает полностью блок данных заданного размера len,
// либо ошибку, либо таймаут.
int ReceivePack(int fd, void *buf, int len, int timeout)
{
  // bla bla bla

  // читаем пока не вычитаем весь блок заданной длины len,
  // иначе вылетаем по тайму - соединение в ауте
  for (int size = 0, r_len = 0; size < len; size += r_len) {
    r_len = 0; // гы

    select(...); // Ждем появления данных, иначе
    // селект вернет либо ошибку, либо тайм
    // тайм - return 1;
    // ошибка - return -1;

    if (данные мона читать?) { // FD_ISSET(...) == ...
      // читаем блок
      r_len = recv(fd, buf, len - size,...);
      if (r_len < 0) {
        // ошибка либо прерывание сигналом, либо что-то тяжелое :-((
        //
        return -1;
      }
    }
  }
  return 0; // прочитан весь блок. Зачет
}

4. Сделать то же самое для send() обязательно. Были случаи на производстве....

Стивенс. "Сетевое программирование". Узнаете столько нюансов ;-))

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх


Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ]
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру