2009-10-26 2 views
0

У меня есть приложение .NET 3.5 C#, которое отправляет 2000-6000 байт-пакетов на машину linux, работающую на sles 10. Машины находятся в одной подсети.Задержки и повторная передача TCP-сокетов

Около 90% времени все работает нормально. Линейная машина обрабатывает мой запрос и отвечает через 5-15 мс. Но около 10% времени, есть примерно 200 мс-800 мс задержки.

Глядя на журналы на машине linux, кажется, что задержка на моем конце. То есть, если мой вызов socket.Send (...) возвращается с 1: 15: 00.000, и я получаю ответ в 1: 15: 00.210, журнал на Linux-машине говорит, что он получил запрос в 1:15 : 00.200, а затем обработали его через 10 мс. (Я использую System.Diagnostics.Stopwatch для синхронизации на моей машине.)

Чтобы отладить, я захватил трафик с помощью wirehark. Вот трафик. Между № 8 и 9 находится время задержки 600 мс. (137.34.210.108 - моя машина, а 137.34.210.95 - это Linux-машина).

"1","11:56:27.380318","137.34.210.95","137.34.210.108","TCP","20700 > 17479 [PSH, ACK] Seq=1 Ack=1 Win=32767 Len=76" 
"2","11:56:27.380393","HewlettP_29:37:0f","Broadcast","ARP","Who has 137.34.210.95? Tell 137.34.210.108" 
"3","11:56:27.380558","HewlettP_29:39:93","HewlettP_29:37:0f","ARP","137.34.210.95 is at 00:1b:78:29:39:93" 
"4","11:56:27.380564","137.34.210.108","137.34.210.95","TCP","17479 > 20700 [ACK] Seq=1 Ack=77 Win=65459 [TCP CHECKSUM INCORRECT] Len=0" 
"5","12:04:48.096892","HewlettP_29:37:0f","Broadcast","ARP","Who has 137.34.210.95? Tell 137.34.210.108" 
"6","12:04:48.097216","HewlettP_29:39:93","HewlettP_29:37:0f","ARP","137.34.210.95 is at 00:1b:78:29:39:93" 
"7","12:04:48.097229","137.34.210.108","137.34.210.95","TCP","17480 > 20600 [PSH, ACK] Seq=1 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=458" 
"8","12:04:48.097457","137.34.210.95","137.34.210.108","TCP","20600 > 17480 [ACK] Seq=1 Ack=4294964377 Win=32767 Len=0 SLE=1 SRE=459" 
"9","12:04:49.700966","137.34.210.108","137.34.210.95","TCP","17479 > 20700 [ACK] Seq=1 Ack=77 Win=65459 [TCP CHECKSUM INCORRECT] Len=1460" 
"10","12:04:49.701190","137.34.210.108","137.34.210.95","TCP","[TCP Retransmission] 17480 > 20600 [ACK] Seq=4294964377 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=1460" 
"11","12:04:49.703970","137.34.210.95","137.34.210.108","TCP","20600 > 17480 [ACK] Seq=1 Ack=4294965837 Win=32767 Len=0 SLE=1 SRE=459" 
"12","12:04:49.703993","137.34.210.108","137.34.210.95","TCP","[TCP Retransmission] 17480 > 20600 [ACK] Seq=4294965837 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=1460" 
"13","12:04:49.704002","137.34.210.108","137.34.210.95","TCP","[TCP Retransmission] 17480 > 20600 [PSH, ACK] Seq=1 Ack=1 Win=64198 [TCP CHECKSUM INCORRECT] Len=458" 
"14","12:04:49.704211","137.34.210.95","137.34.210.108","TCP","20600 > 17480 [ACK] Seq=1 Ack=459 Win=32767 Len=0" 
"15","12:04:49.704215","137.34.210.95","137.34.210.108","TCP","[TCP Dup ACK 14#1] 20600 > 17480 [ACK] Seq=1 Ack=459 Win=32767 Len=0 SLE=1 SRE=459" 
"16","12:04:49.705425","137.34.210.95","137.34.210.108","TCP","20700 > 17479 [PSH, ACK] Seq=77 Ack=1461 Win=32767 Len=44" 

Может кто-нибудь помочь мне интерпретировать это? Я вижу, что происходит повторная передача. Но я не знаю, почему. Коммутатор не показывает сброшенных пакетов. И даже если пакеты теряются, почему для повторной передачи требуется 600 мс?

Я думал, что это (http://support.microsoft.com/kb/328890) может иметь какое-то отношение к задержкам в 200 мс, но я попытался изменить TcpAckFrequency, и это не помогло.

Спасибо, Mike

ответ

3

Начнем с обрезки некоторых из этих выходных данных Wireshark. Мы можем подбрасывать ARP в пакетах 2, 3, 5 и 6. Рассматривая остальные, у вас есть два набора трафика. Пакеты 8 и 9 представляют собой два разных соединения, поэтому вы не можете их сравнить. 7, 8 и 10, однако, являются частью одного соединения, поэтому давайте рассмотрим их.

Пакет 7 - это 458 байт данных, отправляемых в ящик Linux с порядковым номером TCP 1. Однако ACK, который возвращает ящик Linux, составляет 4294964377. Это означает, что Wireshark показывает относительные значения TCP и что Linux box не отправляет ACK для пакета 7, а для более раннего пакета. Затем ваш компьютер ожидает повторного ACK и, когда он его не получит, повторно передает требуемые данные. В этом случае 458 байт из пакета 7 вместе с предыдущими 1002 байтами. Вот почему порядковый номер из пакета 10 соответствует ACK из пакета 8.

К сожалению, это не говорит вам, почему данные отбрасываются. В пакете 8 показано окно Linux, в котором указано, что для этого соединения имеется полный 32-килобайтный буфер ввода («Win = 32767»).

+0

Большое спасибо. Моя ошибка заключалась в том, что я забыл, что одновременно отправлял два пакета на эту машину, один на порт 20600 и один на 20700. Так что я перепутал эти две беседы. Теперь, я думаю, мой вопрос: как я могу сделать повторную передачу быстрее? Почему длительная пауза между дубликатом ack для более раннего пакета и повторной передачей с моего конца? Как я могу сделать это быстрее? –

+0

Можно ли одновременно запускать захват как на вашем ПК, так и на ящике Linux? Это похоже на классический случай, когда пакет не достигает цели. Я предполагаю, что это соединение через LAN с каким-то переключателем. Если это так, возможно, у вас есть другие инструменты для мониторинга общей перегрузки сети. Я не уверен, что вы можете изменить тайм-аут повторной передачи, но в любом случае это похоже на лечение симптомов, а не на причину. –

+0

На самом деле мне удалось значительно сократить количество передач сегодня, увеличив тайм-аут кэша ARP. Я заметил, что, когда прошло более 2 минут между передачами в сокете, вероятность повторной передачи резко увеличилась. Я искал что-то с периодом в 2 минуты и нашел кеш ARP и увеличил его, и за последние несколько часов не было никаких проблем. Но это все еще оставляет два вопроса: 1) Почему увеличение таймаута кэша ARP исправить? 2) Есть ли способ сократить время повторной передачи для тех времен, когда это все еще происходит. –

0

Это показывает только TCP-пакеты на машине Linux, но я бы порекомендовал посмотреть на статистику IP-командой 'NETSTAT -м. Одной из причин повторных передач может быть переполнение буфера сокета, которое будет показано с помощью этой команды.

+0

Вот результат ... TCP статистику для IPv4 Активные открывает = 14801 Пассивные открывает = тысячу сто шестьдесят восемь Неудачные попытки соединения = 116 Сброс соединения = 33 Текущие подключения = 46 Сегменты Полученное = 64272975 Сегменты Переданные = 20797063 Сегменты повторно переданных = 486 UDP Статистика для IPv4 Датаграммы не получил = 25465 нет портов = 52039 Ошибки приема = 7098 Датаграммы Sent = 26223 –

+0

IPv4 Stat стики Получено пакетов = 64340244 Получено заголовка ошибки = 0 Получено ошибки Address = 3230 Датаграммы Forwarded = 0 не указан Протоколы Received = 0 Received отброшенных пакетов = 38 принятых пакетов Поставленные = 64329718 Выходные Запросы = 20827053 –

+0

маршрутизации Выбрасывает = 0 Забракованные Выходные пакеты = 0 Выход Packet Нет маршрута = 0 Reassembly Обязательный = 15207 Повторная сборка Успешные = 5051 Повторная сборка Неудачи = 2587 Датаграммы Успешно Fragmented = 0 Datagrams Failing Fragmentation = 0 Фрагменты созданы = 0 –

0

Я не помню, если Windows имеет это, но в UNIX вы включили бы TCP_NODELAY.

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

int nodelay = 1; 
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); 
+0

Наглинж отключен. Синтаксис очень похож в .NET. sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.NoDelay = true; –

Смежные вопросы