Перехватите связь между сервером и клиентом с помощью tcpdump - PullRequest
2 голосов
/ 27 июля 2010

Я написал простые серверные и клиентские приложения, где я могу переключаться между протоколами TCP, DCCP и UDP. Цель состояла в том, чтобы передать файл из одного в другой и измерить трафик для каждого протокола, чтобы я мог сравнить их для разных сетевых настроек (я примерно знаю, каким должен быть результат, но мне нужны точные цифры / графики). В любом случае, после запуска обоих приложений на разных компьютерах и запуска tcpdump в лог tcpdump я получаю только первые несколько МБ (~ 50 МБ) из моего файла 4 ГБ. Приложения написаны в стандартном коде C / C ++, который можно найти в любом месте в Интернете. В чем может быть проблема или что я тут не так делаю?

- Редактировать

Командная строка, которую я использую:

tcpdump -s 1500 -w mylog

tcpdump захватывает затем пакеты только первые ~ 55 сек . Это время, когда клиент должен отправить файл в сокет. После этого он останавливается, хотя сервер продолжает получать и записывать файл на жесткий диск.

- Редактировать2

Исходный код :

client.cpp
server.cpp
common.hpp
common.cpp

- Редактировать окончательный вариант

Как многие из вас отмечали (и, как я подозревал), в исходном коде было несколько неправильных представлений / ошибок. После того, как я его почистил (или почти переписал), он работает как нужно с tcpdump. Я приму ответ от @Laurent Parenteau , но только для , пункт 5. , поскольку он был единственным, имеющим отношение к проблеме. Если кто-то заинтересован в правильном коде, вот он:

Исходный код отредактирован

client.cpp
server.cpp * *
тысяча пятьдесят-одна
common.hpp
common.cpp

Ответы [ 5 ]

7 голосов
/ 30 июля 2010

В коде много неправильного.

  1. Размер файла / размер передачи жестко задан до 4294967295 байт. Так что, если предоставленный файл не так много байтов, у вас будут проблемы.
  2. В отправителе вы не проверяете, было ли чтение файла успешным или нет. Поэтому, если файл меньше 4294967295 байт, вы не узнаете его и не отправите ненужные данные (или вообще ничего) по сети.
  3. Когда вы используете UDP и DDCP, порядок пакетов не гарантируется, поэтому полученные данные могут быть не в порядке (например, нежелательные).
  4. Когда вы используете UDP, повторная передача потерянного пакета не происходит, поэтому некоторые данные могут никогда не быть получены.
  5. В получателе вы не проверяете, сколько байтов вы получили, вы всегда записываете байты MAX_LINE в файл. Поэтому, даже если вы получите 0 байтов, вы все равно будете записывать в файл, что неправильно.
  6. Когда вы используете UDP, так как вы отправляете в бедренной петле, даже если вызов write () возвращает то же количество отправленных байтов, что и то, что вы запросили, большая часть данных, вероятно, будет отброшена сетевым стеком или сетевой интерфейс, так как нет контроля перегрузки на месте. Итак, вам нужно будет самостоятельно установить контроль над заторами.

И это только из-за быстрого сканирования кода, там, вероятно, больше проблем ...

Мое предложение: Попробуйте выполнить передачу по TCP, выполните md5sum файла, который вы прочитали / отправили, и md5sum файла, который вы получили / сохранили, и сравните 2 md5sum. После того, как этот случай сработает, вы можете перейти к тестированию (все еще используя сравнение md5sum) с UDP и DCCP ...

Для команды tcpdump вы должны изменить -s 1500 на -s 0, что означает unlimited. С помощью этой команды tcpdump вы можете доверять ей, что невидимые ею данные не были отправлены / получены. Еще одна полезная вещь - сравнить вывод tcpdump отправителя с получателем. Таким образом, вы будете знать, произошла ли потеря пакетов между двумя сетевыми стеками.

3 голосов
/ 02 августа 2010

У вас есть x термин? Вместо этого переключитесь на Wireshark и попробуйте с этим - его бесплатный, с открытым исходным кодом, и, вероятно, более широко используемый сегодня tcpdump. (Ранее он был известен как Ethereal.)

Также попробуйте следующие параметры tcpdump:

  • -xx также печатать заголовок ссылки и данные пакета (-w записывает данные?)
  • -C явно указывает максимальный размер файла.
  • -U записывать пакет за пакетом в файл вместо очистки буфера.
  • -p не ставить ник в беспорядочном режиме
  • -O не использовать оптимизатор сопоставления пакетов, поскольку у вас новый протокол уровня приложения.
  • Используете ли вы подробный вывод в tcpdump? Это может привести к быстрому заполнению буферов, поэтому при запуске он перенаправляет stdout / err в файл.

Это гигабитная сетевая карта на обоих концах?

2 голосов
/ 04 августа 2010

"Это время, необходимое клиенту для отправки файла в сокет. После этого он останавливается, даже если сервер продолжает получать и записывать файл на жесткий диск."

Этот звук действительно странный.Буферы сокетов слишком малы, чтобы это могло произойти.Я действительно думаю, что ваш серверный код, кажется, только получает данные, в то время как отправитель фактически уже прекратил отправку данных.

2 голосов
/ 04 августа 2010

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

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

В этом коде есть условия гонки, которые в некоторых ситуациях приводят к недетерминированному поведению,неправильно обрабатывает '\0' как специальное значение в сетевых данных, игнорирует условия ошибки и условия конца файла.И это только краткое прочтение.

В этом случае я почти уверен, что tcpdump функционирует отлично, и говорю вам, что ваше приложение не делает то, что вы думаете.

0 голосов
/ 03 августа 2010

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

Попробуйте sync или просто подождите немного, пока не убедитесь, что было передано достаточно данных.

...