В Linux как узнать, получен ли ACK для определенного TCP-пакета? - PullRequest
1 голос
/ 14 января 2009

Короче говоря: в Linux, как я могу убедиться, что ACK-сообщение получено для определенного TCP-пакета?

Полная история:

Я отлаживаю проблему Asterisk / OpenH323 <-> Panasonic IP-GW16.

Соединение H323 включает два сеанса: H225.0 и H245. Это всего два сеанса TCP, по которым передаются некоторые данные.

Давайте назовем их Session 1 (для H225.0) и Session 2 (для H245).

Session 1 имеет хорошо известный номер TCP-порта 1720, в то время как порт для Session 2 выбирается во время выполнения.

Управление потоком происходит следующим образом:

  1. Panasonic вызывает Asterisk: он открывает Session 1 (TCP / 1720) для Asterisk и отправляет сообщение SETUP через Session 1, которое содержит port 2, которое Panasonic будет слушать.
  2. Asterisk отправляет Panasonic сообщение о вызове через Session 1
  3. Panasonic начинает слушать на port 2
  4. Panasonic отправляет TCP ACK через Session 1.
  5. Asterisk открывает TCP Session 2 на port 2.

Порядок шагов 2 и 3 важен: Panasonic не будет слушать port 2, пока не получит сообщение CALL PROCEEDING на step 2.

Но в коде OpenH323 step 2 и step 5 находятся всего в нескольких строках.

Именно поэтому соединение sometimes работает в режиме отладки, а quite never работает в выпуске.

Это хорошо видно по дампу пакета. Я провел серию экспериментов, и в 52 случаях из 52, если step 5 идет до step 4, соединение не устанавливается; если нет, соединение установится успешно.

Нет никаких других сообщений от Panasonic, кроме того, что ACK в step 4, и кажется, что Asterisk может узнать, что прослушивается port 2, только получение этого ACK.

Конечно, я могу реализовать временное ожидание, но я хочу более чистое решение.

Итак, вопрос повторяется: после отправки сообщения по TCP-соединению в step 2, как узнать, получен ли ACK для пакета, содержащего сообщение?

Ответы [ 3 ]

3 голосов
/ 14 января 2009

В этом конкретном случае я бы сказал, что вы обнаружите, что ваша структура tcp_info будет содержать ненулевой tcp_info.tcpi_unacked. Вы получите это через getsockopt(TCP_INFO).

Примечание: нестабильный интерфейс, по-видимому.

1 голос
/ 29 октября 2011

ACK уровня TCP отправляется операционной системой и может быть отправлен до того, как процесс прочитает данные. Поэтому, если вы получаете ACK, это не означает, что удаленное приложение действовало на сообщение или даже было уведомлено о его существовании.

Только представьте: если TCP подтверждает, что мы являемся подтверждением сообщения, приложение должно прочитать () сообщение, обработать его (что может занять некоторое время) и затем вызвать системный вызов read_ok. Насколько я знаю, это невозможно при стандартном API сокетов.

Вы можете быть в состоянии проверить, есть ли какие-либо неопакованные данные с SIOCOUTQ ioctl (man 7 tcp). Но это не надежное решение вашей проблемы.

Вы уверены, что именно так должен работать h323? Что если port2 недействителен или занят другим соединением? Подтверждение или ошибка должны быть отправлены обратно.

0 голосов
/ 14 января 2009

Временная последовательность кажется странной, хотя, если Panasonic использует проприетарную операционную систему, которая может это объяснить.

Чтобы уточнить - AIUI - если бы Panasonic выполнял "нормальную" операцию O / S, ACK, отправленный им на этапе 4, произойдет сразу после того, как программное обеспечение Panasonic получит read() данных из управляющего сокета TCP.

Аналогично, вызов кода OpenH323 для write() (на шаге 2) не должен возвращаться ( при условии, что это не неблокирующая розетка !), Пока ACK от Panasonic не будет получен Звездочка сервера. То, что - это то, как вы должны знать, что ACK получен.

По сути, кажется, что Panasonic не делает эквивалент listen() во втором сокете, пока не получит read() сообщение CALL PROCEEDING. Это похоже на состояние гонки - иногда Open323 пытается connect() до того, как другой конец будет готов.

Когда это происходит, вы получаете ECONNREFUSED на конце OpenH23?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...