Лучшие варианты сокетов для клиента и сервера, которые непрерывно передают данные - PullRequest
3 голосов
/ 07 июля 2010

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

  • SO_LINGER
  • SO_KEEPALIVE
  • SO_NODELAY
  • SO_REUSEADDRESS
  • SO_SENDBUFFER
  • SO_RECBUFFER
  • TCP_NODELAY

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

Что было бы наилучшим вариантом для установки в соответствии с описанным выше сценарием, и есть ли что-то, что мы могли бы сделать с нашей стороны (программно или опционально), чтобы попытаться минимизировать количество разрывов соединения. Мы используем обычный TCP / IP.

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

Ответы [ 6 ]

6 голосов
/ 20 июля 2010

Строго говоря, вам не нужны никакие из этих опций сокетов:

* SO_LINGER

Вам нужно установить SO_LINGER только в том случае, если ваше приложение все еще имеет ожидающие отправки пакеты при вызове close(2) или shutdown(2). Не совсем применимо для вашего приложения.

* SO_KEEPALIVE

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

* SO_NODELAY

Это (предположительно псевдоним для TCP_NODELAY) отключает Алгоритм Нейгла , который является просто проблемой избежания небольших пакетов. Возможно, Nagle мешает вашему приложению, но для обработки задержек в 500 мс требуются специальные последовательности пакетов; он никогда не просто вешает соединения.

* SO_REUSEADDRESS

Полезно для всех «серверов», которые прослушивают общеизвестные номера портов; использование «клиентов» почти всегда закрывает какую-либо ошибку или иное, но иногда это необходимо, если запросы должны поступать с хорошо известного номера порта.

* SO_SENDBUFFER
* SO_RECBUFFER

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

* TCP_NODELAY

Отключает Нэгла. Маловероятно, чтобы сделать больше, чем ввести задержки 500 мс, если ваше приложение отправляет несколько небольших пакетов перед попыткой чтения блокировки.

Действительно, вам не нужно устанавливать какие-либо параметры сокетов.

Можете ли вы перевести свой код во что-то, что можно вставить сюда, проверить или проверить? Я привыкла к тому, что сеансы TCP выживают без проблем несколько дней или недель, так что это довольно удивительно.

2 голосов
/ 14 июля 2010

Во-первых, я думаю, что эта страница актуальна в отношении полуоткрытых соединений.http://nitoprograms.blogspot.com/2009/05/detection-of-half-open-dropped.html

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

Поскольку вы пишете клиент и сервер, я бы не стал полагаться на TCP, чтобы сообщать вам, когда соединение вообще разрывается.Я просто хотел бы, чтобы сервер также подтвердил получение результата от клиента.Тогда обе стороны будут ожидать немедленных ответов на свои сообщения, и вы сможете отслеживать, какие сообщения были подтверждены, и установить соответственно небольшой тайм-аут для получения подтверждения.Это не время ожидания отправки или получения, а время между отправкой сообщения и получением подтверждения для этого сообщения.Затем вы можете установить время ожидания соответствующим образом в зависимости от качества вашего соединения (например, очень маленькое, если вы работаете по шлейфу, но большое, если вы используете беспроводную связь со слабым сигналом).захочет использовать SO_REUSEADDRESS, чтобы вам не помешали повторно открыть сокет, например, если он не завершил закрытие из ранее завершенного процесса.

1 голос
/ 19 июля 2010

Возможно, у вас есть, но лучше проверить очевидное ....

Вы убедились, что истекает время сокета, а не ваш код? Сокеты довольно стабильны, и, хотя где-то может быть проблема, кажется, что она есть в вашем коде. Я бы использовал журналы, метки времени и синхронизированные часы, чтобы быть уверенным.

Может быть, проблема в том, что вы действительно ДОЛЖНЫ потратить много времени, чтобы выполнить вычисление, поэтому, возможно, добавив сообщение «Я все еще думаю об этом» в ваш протокол, который регулярно отправляется, чтобы поддерживать соединение?

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

0 голосов
/ 19 июля 2010

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

Недостатком является то, что этот стол может стать очень большим, поэтому его необходимо обрезать, когда соединения закрыты или они кажутся просто устаревшими и тихо умирают. Соединение, которое замолчало в течение 20 минут, обычно достаточно тихое, чтобы пожать. (Это действительно очень быстро, так как TCP KEEPALIVE обычно занимает два часа, что делает его практически бесполезным перед лицом брандмауэров NAT.)

Итак: это происходит через брандмауэр NAT? Является ли связь тихой для длинных отрезков? Если это так, добавьте ping / pong к вашему протоколу и запускайте его каждые несколько минут.

0 голосов
/ 19 июля 2010

Я настоятельно рекомендую вам использовать модель ping / echo между клиентом и сервером, так что если в течение x секунд данные не отправляются, необходимо отправить сообщение ping. Типичной причиной перерыва может быть брандмауэр, который отключает сокеты из-за неактивности.
Типичная проблема, где модель TCP терпит неудачу, является физическими проблемами, например выдернутый / сломанный кабель и висит на одной стороне, где технически кто-то слушает, пока не начнется переполнение очереди (что может никогда не произойти, учитывая ваш объем данных).

0 голосов
/ 13 июля 2010

попробуйте эти варианты SO_LINGER - для уточнения, когда вызывается Socket close s, а некоторые неотправленные данные в очереди TCP_NODELAY - для неблокирующей передачи данных

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