У меня есть TCP-сервер, построенный с сокетами на Python. Приложение, которое я создаю, зависит от времени, поэтому важна целостность данных, поэтому нам нужен TCP. Пропускная способность очень низкая.
И есть клиент, который запрашивает данные с сервера каждые 50 мс. В ответ клиент получает сообщение OK, если на сервере нет данных или фактически требуемых данных.
Каждый раз, когда клиент делает запрос к серверу, он отправляет фрейм из 5 байтов (не считая 40 дополнительных байтов, поступающих от IP и TCP). С другой стороны, сервер отвечает либо кадром размером 5 байтов (в большинстве случаев), либо кадром размером> 70 байтов (обычно каждую секунду).
С двух сторон розетки ставятся так:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # this line is excluded in client's case
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 8192)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.settimeout(0.5)
В локальной сети все работает нормально (без задержек), но всякий раз, когда я подключаюсь к серверу с общедоступного IP-адреса (я перенаправляю порт), он сильно тормозит. Задержка может доходить до 15 секунд (в этот момент время истекает), что невероятно много. Большую часть времени RTT остается на уровне 200–210 мс. В WireShark я вижу много (ложных) повторных передач и дублирующих ACK.
Что я могу сделать? Я уже отключил алгоритм Нэгла, но пока безуспешно.
Я внимательно просмотрел предоставленные файлы захвата, и вот мой анализ. В итоге, Я считаю, что это проблема вашего маршрутизатора, который выглядит как Разноцветный какое-то устройство.
Если посмотреть конкретно на трафик от клиента к серверу, подавляющее большинство сеансов начинается нормально, но затем происходит потеря пакетов, что приводит к повторным передачам от клиента и тайм-аутам. Например, проверьте номер пакета 161–207. В пакете 161 клиент отправляет пакет данных на сервер, но не получает ответа, в результате чего клиент повторяет передачу в течение примерно 15 секунд, прежде чем соединение будет разорвано.
Большинство TCP-потоков демонстрируют такое поведение, поэтому можно сделать вывод, что либо пакеты данных от клиента не достигают сервера, либо ответ сервера не достигает клиента.
Что касается задержки, то между ответами SYN и SYN / ACK от сервера существует значительная (и непостоянная) задержка в диапазоне от 168 мс до 770 мс.
Если вы примените фильтр отображения wirehark для tcp.stream eq 1 || tcp.stream eq 2
вы можете видеть обе стороны общения. В частности, Клиент> Брандмауэр, а затем Брандмауэр> Сервер (и наоборот). Опять же, все начинается нормально, а затем вокруг пакета 407 все становится интересным.
Пакет № 407 отмечает момент, когда клиент отправляет на сервер порцию новых данных. Маршрутизатор получает это и пересылает на сервер. Сервер отправляет обратно пакет подтверждения (пакет № 410), а также другой небольшой пакет данных (№ 411). Однако мы не видим, что маршрутизатор передает эти пакеты обратно клиенту. - это лучшее доказательство, которое я нашел, что это проблема маршрутизатора.
Сравните это с одним из многих успешных обменов немного дальше по трассировке - например, пакеты с 394 по 406:
Когда что-то выходит из строя, все останавливается после этапа 4 - два пакета, отправленные с сервера, кажутся отброшенными на маршрутизаторе.