1. Засылаем пакет (610 байт)
2. Он лежит в буфере сокета (видимо ACK действительно нет. почему ?)
3. Засылаем второй пакет (610 байт). Теперь у нас там лежит 1220. Жду...
4. Минут через 15 говорю netstat - опа ! А соединения уже нет. Кстати, на другой стороне (в другом городе нашей необъятной Родины) netstat утверждает что ESTABLISHED - весело.
5. Пытаюсь записать туда третий пакет. И только сейчас получаю облом в виде любимого SIGPIPE ! Ну слава богу, хоть так просигнализировал.
Итого: два пакета якобы ушли, на самом деле были потерянны. И еще один явно не ушел.
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp4 0 0 xxxx.4001 yyyy.1225 ESTABLISHED
tcp4 0 1220 xxxx.4000 yyyy1224 ESTABLISHED
В сокете на отправку лежат 1220 байт, и не уходят !
#define SOCKET_ERROR -1
...
int flag;
flag = 0;
int res = send( m_sock_writer, buffer, packetSize + sizeof(long), flag );
if( res == SOCKET_ERROR )
{
m_log->Msg( 1, "WARNING ! Send socket was closed ! Restart your client !\n" );
// We will restart writer socket in READ function !
// READ function always catch error in connection, becouse stay on recv()
delete[] buffer;
return;
}
m_log->Msg( 0, "WRITER: OK.\n" );
---
Вот так, send() мне не возвращает -1. Типа все отправил, все ок. А на самом деле данные лежат в очереди, и их не могут получить.
Кто с такой фигней встречался ? Из-за чего может быть ?
P.S. OS: FreeBSD
P.P.S: блин, ну почему в виндах ни разу такой фигни не возникало !
Требуется помощь...06.06.03 14:17 Автор: PS <PS> Статус: Elderman
В продолжение топика.
Ситуация сложиласть следующим образом:
Есть некий хост CCC, за ним сидят две машины AAA и BBB.
Если мы запустим клиент с машины AAA, то описанной в топике проблеммы не будет. Если запусим с BBB то проблемма возникает стабильно.
Коннект клиентов идет к некому хосту DDD.
Было произведенно сравнение параметров ядра машин AAA и BBB.
В листиге: AAA это <
BBB это >
И так < - работает нормально
> - теряет соединение после таймаута.
Кто знает за что отвечают нижеприведенные настройки, будте добры написать. И какая из настроек может вызывать проблемму.
> В продолжение топика. > Ситуация сложиласть следующим образом: > Есть некий хост CCC, за ним сидят две машины AAA и BBB. > Если мы запустим клиент с машины AAA, то описанной в топике > проблеммы не будет. Если запусим с BBB то проблемма > возникает стабильно. > Коннект клиентов идет к некому хосту DDD. > > Было произведенно сравнение параметров ядра машин AAA и > BBB. > В листиге: AAA это < > BBB это > > Вот за это спасибо. Такому челу и помочь приятно. Вот если бы ты ещё сказал, есть ли там ipf/ipfw и привел бы их правила...
> < net.inet.ip.forwarding: 1 > --- > > net.inet.ip.forwarding: 0 Это - гейтовать или нет. Вряд ли оно.
> > net.inet.ip.dummynet.hash_size: 64 ...
> > net.inet.ip.dummynet.red_max_pkt_size: 1500 Настройки dummynet'а могут в принципе гадить если траффик идет через кривые пайпы. Это задается в правилах ipfw
> < net.inet.ip.fw.verbose_limit: 0 > --- > > net.inet.ip.fw.verbose_limit: 100 > 32c43 man ipfw, в данном случае роли не играет.
> < net.inet.ip.fw.dyn_count: 107 > --- > > net.inet.ip.fw.dyn_count: 0 > 34c45 > < net.inet.ip.fw.static_count: 34 > --- > > net.inet.ip.fw.static_count: 1 > 42,44c53 Судя по этим строчкам, на ААА стоит фаервол с 34 правилами. Кроме того там есть динамические правила. Но все это нас не колышет, так как на AAA проблем нету. На ВВВ правило одно. Что-то мне подсказывает что оно выглядит как
65535 allow ip from any to any
Выходит ipfw не гадит.
> < net.inet.ip.maxfragpackets: 79 > < net.inet.ip.maxfragsperpacket: 16 > < net.inet.ip.sendsourcequench: 0 > --- > > net.inet.ip.maxfragpackets: 632 > 52c61 не должно колыхать.
> < net.inet.tcp.rfc1323: 0 > --- > > net.inet.tcp.rfc1323: 1 > 70c79 Вот здесь может быть проблема. Я посмотрел по диагонали rfc1323 - "TCP Extensions for High Performance". Попробуй поменять этот oid
> < net.inet.tcp.pcbcount: 22 > --- > > net.inet.tcp.pcbcount: 15 > 77d85 я думаю что это кол-во PCB. Из названия. Про PCB - по моему rfc0793
> < net.inet.tcp.inflight_stab: 20 > 120c128 не знаю. надо гуглить.
> < net.link.generic.system.ifcount: 8 > --- > > net.link.generic.system.ifcount: 3 кол-во интерфейсов? не должно колыхать.
> 127a136,150 > > net.link.ether.bridge_cfg: > > net.link.ether.bridge: 0 > > net.link.ether.bridge_ipfw: 0 > > net.link.ether.bridge_ipf: 0 > > net.link.ether.bridge_ipfw_drop: 0 > > net.link.ether.bridge_ipfw_collisions: 0 > > net.link.ether.verbose: 0 > > net.link.ether.bdg_split_pkts: 0 > > net.link.ether.bdg_thru: 0 > > net.link.ether.bdg_copied: 0 > > net.link.ether.bdg_copy: 0 > > net.link.ether.bdg_predict: 0 > > net.link.ether.bdg_fw_avg: 0 > > net.link.ether.bdg_fw_ticks: 0 > > net.link.ether.bdg_fw_count: 0 настройки бриджа. появляются если скомпилить ядро с опцией BRIDGE. но так как бридж задизаблен (net.link.ether.bridge: 0), не колышет.
Резюме.
tcpdump в зубы и сравнивай две сессии. Это не так уж много работы. А если хочется легких путей - попробуй тупо поменять net.inet.tcp.rfc1323
А вот сделующий представляет интерес. К сожеленью я забыл отключить "показ портов в текстовом виде", а сокет, видимо, хватанул 1110 порт, так что с nfsd-status придеться мириться ;(
Итак я получил 13ю ошибку - "host unreachable - admin prohibited filter".
Почему ? Десять минут назад пакеты уходили и все было хорошо, что изменилось ?! Из-за чего такое может происходить. Почему только на BBB ?
Вообщем в моей голове kernel panic. Help !
P.S. Еще я забыл сказать, как теперь кажется, самое главное. Хоть хосты AAA и BBB сидят за CCC, но AAA имеет свой внешний адрес, т.е. использует CCC только как роутер, BBB наоборот - полностью локальная машина для сети, и использует CCC как "nat сервер". Может тут собака порылась ?
> Наконец то я продампил пакет. К сожалению дамп сделан > только на серверной стороне. > > Обозначения те же: AAA - работающий хост, BBB - не > работающий хост, DDD - хост сервера. >
если ты дампил на стороне DDD, а ВВВ сидит за натом, выходит пакеты от ВВВ имеют обратный адрес CCC. Так?
> скипаем дамп...
> > Итак я получил 13ю ошибку - "host unreachable - admin > prohibited filter". > > P.S. Еще я забыл сказать, как теперь кажется, самое > главное. Хоть хосты AAA и BBB сидят за CCC, но AAA имеет > свой внешний адрес, т.е. использует CCC только как роутер, > BBB наоборот - полностью локальная машина для сети, и > использует CCC как "nat сервер". Может тут собака порылась > ? Вполне может быть.
Я не знаю, что за софтина делает нат на ССС, узнай это. Но пока могу сделать следующее предположение о принципе её работы:
Приходит Syn от ВВВ к DDD.
Создается структура примерно такого вида:
struct NATed_conn {
dword src_ip;
dword dst_ip;
word src_port;
word dst_port;
word proto;
word nated_port;//Optional если нат изменяет срц_порт
dword lastused;
}
После чего, каждый пакет проходящий через нат сравнивается по своим 5 определяющим параметрам (срц_ип,срц_порт,дст_ип,дст_порт,прото) со сриском таких структур, и если находится соответствие, хедеры переписываются, а в lastused записывается текущее время (тики, секунды, [micro|nano|pico|mega]секунды - что там у них есть). Если пакет является последним фином для тцп коннекшена, то структура удаляется (память-то не резиновая). А как быть с коннекшенами которые закончились аномально, без финов? Или с UDP коннекшенами, у которых финов вообще нету? Пишется функция remove_stale_conns , которая иногда пробегает по списку и выкидывает те структуры для которых getcurtime-lastused>N . Понятно? Или, если количество структур ограничено, и некуда вставить новую, демон находит коннекшен с самым старым lastused и выкидывает его чтобы вставить новый. Я думаю что нечто подобное произошло на машине CCC с твоим соединением. А когда оно перестало натится, пакет
18:15:24.245272 DDD.4001 > BBB.2844: . ack 50 win 58400 (DF)
пошел не к BBB а к ССС, а там ему выдали "от ворот поворот" в виде ICMP13 (это наверное фаерволл).
Выводы:
1. Узнай что за нат-демон стоит на ССС.
2. Постарайся узнать его принцип работы, если не сможешь, спроси на форуме.
3. Если проблема в нат-демоне, включи опцию SO_KEEPALIVE в клиентском сокете. Прога в сорцах, или в бинарнике? В любом случае это можно сделать. Ну вот собссно и все :)
И в заключение...09.06.03 13:50 Автор: PS <PS> Статус: Elderman
Но опять же - это не панацея. Я решил что лучший способ узнать о доставке пакета - это подтверждение. На каждый отправленный пакет нужно ждать подтверждение, если в течении некоторого времени его нет - считаем связь разорванной. На это все и было переписанно (счастливые, у вас были выходные... :( )
Кстати зашел вчера вечерком в один книждый магазинчик, там стоит книжечка по TCP/IP, желтенькая такая, трехтомная. Нашел нужную тему, а там русским по белому написанно, что для надежной доставки по TCP нужно самому реализовывать пакеты подтверждения. О как ! (от себя добавлю - на это можно, конечно, забить. И в большитстве случаев все работать будет. Но рано или поздно софт нарвется на то состояние в сети, о котором вся эта ветка ).
Еще одна фигня с send04.06.03 19:08 Автор: NKritsky <Nickolay A. Kritsky> Статус: Elderman
> Proto Recv-Q Send-Q Local Address Foreign Address > (state) > tcp4 0 0 xxxx.4001 yyyy.1225 ESTABLISHED > tcp4 0 1220 xxxx.4000 yyyy1224 ESTABLISHED > > В сокете на отправку лежат 1220 байт, и не уходят ! > Вот так, send() мне не возвращает -1. Типа все отправил, > все ок. А на самом деле данные лежат в очереди, и их не > могут получить. > > Кто с такой фигней встречался ? Из-за чего может быть ? Первое что приходит в голову - нет места в окне TCP сессии. То есть - не пришел подтверждающий ACK на пакет № N а мы уже заслали N+K пакетов вперед. Подробности давай, посмотрим.
Вот например вопросы:
1. Нельзя ли получить tcpdump лог сессии.
2. Что значит "данные лежат в сессии"? Сколько они там лежат, погибает ли сокет по таймауту, жив ли удаленный хост, удаленный процесс.
Ага, дело было так04.06.03 19:27 Автор: PS <PS> Статус: Elderman
1. Засылаем пакет (610 байт)
2. Он лежит в буфере сокета (видимо ACK действительно нет. почему ?)
3. Засылаем второй пакет (610 байт). Теперь у нас там лежит 1220. Жду...
4. Минут через 15 говорю netstat - опа ! А соединения уже нет. Кстати, на другой стороне (в другом городе нашей необъятной Родины) netstat утверждает что ESTABLISHED - весело.
5. Пытаюсь записать туда третий пакет. И только сейчас получаю облом в виде любимого SIGPIPE ! Ну слава богу, хоть так просигнализировал.
Итого: два пакета якобы ушли, на самом деле были потерянны. И еще один явно не ушел.
И как с этим работать ?
Немножко уточним.04.06.03 19:41 Автор: NKritsky <Nickolay A. Kritsky> Статус: Elderman
1. Это произошло один раз, или это регулярные/постоянные траблы?
2. Если удастся повторить - сможешь снять tcpdump?
3. Хоть что-нибудь проходит по этому соединению, или фигня начинается при первых же 1220 байтах?
4. Кстати, может говорить не бАйты а байтА, типа как профессиональный жаргон (мы говорим не штОрмы а штормА), но это так, slightly offtopic.
5. Остальные ТСР соединения между этими двумя серверами - работают?
> 1. Это произошло один раз, или это регулярные/постоянные > траблы?
Регулярные.
> 2. Если удастся повторить - сможешь снять tcpdump?
Если ничего другого не поможет - то придется.
> 3. Хоть что-нибудь проходит по этому соединению, или фигня > начинается при первых же 1220 байтах?
Так, сначала (после accept) все идет просто отлично. Потом я иду курить, чел на другой стороне идет курить... мы курим где то 20 минут. И вот после такого таймаута send прекращает что либо посылать. (мистика, борьба FreeBSD с табакокурением)
> 4. Кстати, может говорить не бАйты а байтА, типа как > профессиональный жаргон (мы говорим не штОрмы а штормА), но > это так, slightly offtopic.
No comments.
> 5. Остальные ТСР соединения между этими двумя серверами - > работают?
Есть еще одно соединение, на другой стороне в него делают send, я делаю только recv. Оно работает стабильно.
а если чел с той стороны через 20 мин пакет пошлет с его стороны соединение рвется? (RST)07.06.03 14:34 Автор: Killer{R} <Dmitry> Статус: Elderman
> > 2. Если удастся повторить - сможешь снять tcpdump? > > Если ничего другого не поможет - то придется. Слушай, этож совсем нетрудно. По крайней мере на твоей стороне. Я всегда это делаю одним из первых шагов.
> > > 3. Хоть что-нибудь проходит по этому соединению, или > фигня > > начинается при первых же 1220 байтах? > > Так, сначала (после accept) все идет просто отлично. Потом > я иду курить, чел на другой стороне идет курить... мы курим > где то 20 минут. И вот после такого таймаута send > прекращает что либо посылать. (мистика, борьба FreeBSD с > табакокурением) > О ! После таймаута. А что если я спрошу - есть ли между вами firewall'ы? И есть ли там правила вроде FreeBSDшных keep-sate? Мне кажется, что это могло бы стать причиной. Что если включить SO_KEEPALIVE на сокете?