Мне нужна опция TCP (ioctl) для немедленной отправки данных - PullRequest
7 голосов
/ 03 ноября 2008

У меня необычная ситуация: я использую систему Linux во встроенной ситуации (Intel Box, в настоящее время использует ядро ​​2.6.20), который должен взаимодействовать со встроенной системой, в которой частично нарушена реализация TCP , Насколько я могу судить прямо сейчас, они ожидают, что каждое наше сообщение придет в отдельном кадре Ethernet! Кажется, у них проблемы, когда сообщения разбиты по фреймам Ethernet.

Мы находимся в локальной сети с устройством, и между нами нет маршрутизаторов (только коммутатор).

Мы, конечно, пытаемся заставить их исправить свою систему, но это может оказаться неосуществимым.

Я уже установил TCP_NODELAY на своих сокетах (я подключаюсь к ним), но это помогает, только если я не пытаюсь отправить более одного сообщения за раз. Если у меня есть несколько исходящих сообщений подряд, эти сообщения, как правило, оказываются в одном или двух кадрах Ethernet, что вызывает проблемы в другой системе.

Обычно я могу избежать этой проблемы, используя таймер, чтобы избежать посылки сообщений слишком близко друг к другу, но это, очевидно, ограничивает нашу пропускную способность. Кроме того, если я уменьшу время до минимума, я рискую перегружать сеть, задерживая передачу пакетов и в конечном итоге допуская более одного моего сообщения в один и тот же пакет.

Можно ли как-нибудь определить, есть ли у драйвера данные в очереди или нет? Есть ли способ заставить драйвер отправлять независимые вызовы записи в пакетах независимого транспортного уровня? Я просмотрел справочные страницы по socket (7) и tcp (7) и ничего не нашел. Может быть, я просто не знаю, что ищу.

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

Любая помощь с благодарностью.

Ответы [ 6 ]

9 голосов
/ 03 ноября 2008

IIUC, установка опции TCP_NODELAY должна сбрасывать все пакеты (т.е. tcp.c реализует настройку NODELAY с помощью вызова tcp_push_pending_frames). Поэтому, если вы устанавливаете опцию сокета после каждого звонка, вы должны получить то, что хотите.

2 голосов
/ 05 ноября 2008

Вы не можете обойти проблему, если не уверены, в чем проблема.

Если они совершили ошибку новичка, предполагая, что recv () получает ровно одно сообщение, то я не вижу способа решить его полностью. Отправка только одного сообщения на кадр Ethernet - это одно, но если несколько кадров Ethernet поступят до того, как получатель вызовет recv (), он все равно получит несколько сообщений за один вызов.

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

1 голос
/ 03 ноября 2008

Может быть, установить TCP_NODELAY и установить свой MTU достаточно низким, чтобы в каждом кадре было не более 1 сообщения? Да, и добавьте флаг "не фрагментировать" на исходящих пакетах

0 голосов
/ 03 ноября 2008

Может быть, вы могли бы попытаться перевести стек tcp в режим низкой задержки:

echo 1 > /proc/sys/net/ipv4/tcp_low_latency

Это должно способствовать выбору пакетов как можно быстрее по сравнению с объединением данных. Прочитайте man по tcp (7) для получения дополнительной информации.

0 голосов
/ 03 ноября 2008

В худшем случае вы могли бы пойти на один уровень ниже (необработанные сокеты), где вы лучше контролируете отправленные пакеты, но тогда вам придется иметь дело со всеми мелочами TCP.

0 голосов
/ 03 ноября 2008

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

...