Можно ли сломать сокет TCP, чтобы он все еще получал, но больше не мог отправлять? - PullRequest
0 голосов
/ 25 мая 2018

Занимался программированием с сокетами в течение 15 лет и никогда не сталкивался с этим раньше.

Запуск стандартного сервера сокетов TCP, клиенты подключаются к нему, и сообщения отправляются туда и обратно через открытый сокет.Это игровой сервер, на котором клиент действует в игровом мире, на котором работает сервер.Этот сервер обработал 1,6 миллиона таких сеансов сокетов за последние 3 месяца.

Сервер регистрирует сообщения, полученные от клиента.Клиент регистрирует сообщения, полученные от сервера, а также регистрирует сообщения, которые он отправляет на сервер.

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

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

Сервер в итоге обнаружил, что клиент простаивал, отправил сообщение на прощание и закрыл соединение.Клиент даже получил сообщение прощания.

Этот процесс длился 18 секунд (с момента, когда сервер получил последнее сообщение от клиента, до времени, когда он отправил сообщение прощания).

Вопрос: возможно ли такое поведение для сокета TCP?Где он ломается или глохнет только в одном направлении?

Я думаю о злых чарах, которые должны пройти.Если маршрут клиент-> сервер нарушен, сервер больше не будет получать подтверждения.Это означает, что сервер будет повторно посылать все пакеты снова и снова по истечении времени ожидания.Но это не значит, что он перестанет посылать новые пакеты.Клиент также не получит никаких подтверждений для пакетов, которые он отправляет, но по другой причине (пакеты не проходят вообще, поэтому сервер не может их подтвердить), поэтому он также будет иметь тайм-аути повторная отправка.

Возможно, это не вопрос TCP, а вопрос сетевой маршрутизации.Может ли двухсторонний маршрут прорваться только в одну сторону?

1 Ответ

0 голосов
/ 25 мая 2018

Я думаю, что это проблема маршрутизации.Другие комментарии, приведенные выше относительно однонаправленного трафика, применимы только в отношении shutdown(2), который, по-видимому, вы должны знать, поскольку ваше приложение должно делать это явно.

Маршрутизация могла бы быть различной в двух направлениях.(как заметил @RonMaupin).Или может случиться так, что на каком-то промежуточном маршрутизаторе было просто большое количество заторов в одном направлении.Любая ситуация может привести к отбрасыванию пакетов.

Перед лицом пропущенных пакетов, подобных этому, обе стороны будут продолжать повторять свои передачи из-за не получения ACK (что, я думаю, вы правильно описали).Начальное время повторной передачи основано на приблизительном времени прохождения сигнала туда и обратно, рассчитанном каждой конечной машиной.Затем происходит экспоненциальный откат для последующих повторных передач - см., Например, http://www.pcvr.nl/tcpip/tcp_time.htm#21_2 для объяснения.Результатом является возможное время ожидания.

С учетом экспоненциального отката и некоторого количества повторных передач (это число зависит от платформы и часто настраивается), как правило, требуется больше 18 секунд, прежде чем стек локальной сети объявляет сеанс мертвым.Но, похоже, ваше приложение, возможно, замкнуло этот процесс по своему собственному таймауту (что кажется разумным для игрового сервера).

Я подозреваю, что вы никогда не видели этого раньше, потому что в целом маршрут одинаков в обоих направлениях, а когда маршрутизатор "выключен", он в обоих направлениях не работает.

...