N * (подключение отправка закрытие) против (отключение Nagle подключение N * отправка закрытие), N > 1

#c #c #network-programming #sockets

#c #c #сетевое программирование #сокеты

Вопрос:

Я новичок в программировании сокетов (как вы уже поняли из моего глупого вопроса), но, не обращая внимания на мой стыд, я пишу программу, использующую TCP posix. Мое ограничение заключается в следующем: сообщение, которое должно быть отправлено с клиента на сервер, должно быть прочитано как поток байтов, и, хотя мое приложение не отличается высокой производительностью, сообщение должно быть доставлено как можно скорее. Я написал класс TCP-клиента с намерением выполнить следующее: 1 подключение — множество отправок — и 1 закрытие в конце потоковой передачи. Проблема в том, что сообщения не доставляются почти в режиме реального времени (я предполагаю, что они ожидают получения большего пакета для лучшей пропускной способности) Проведя некоторое исследование в Интернете, я обнаружил, что, хотя вы можете отключить алгоритм Nagle (NA), это очень плохая идея сделать это. Поскольку я новичок в программировании сокетов, я не хочу отключать функции, которые я не до конца понимаю. Итак, у меня осталось два (плохих?) варианта:

  1. подключение — отправка- закрытие для каждого сообщения
  2. 1 подключить — отправить несколько раз и выполнить 1 закрытие в конце с отключенным NA. Хотя я читаю последствия отключения NA, мне кажется, что открывать и закрывать сокет каждый раз только для отправки сообщения — это тоже дорогая цена, которую приходится платить.

Существуют ли другие решения без выхода из сокетов?

Спасибо.

Комментарии:

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

Ответ №1:

В вашем случае отключение Nagle — это именно то, что вы хотите сделать.

Просто помните, что каждый вызов write() будет немедленно передавать ваши данные. Поэтому убедитесь, что вы упаковываете все свое сообщение вместе, а затем вызываете write() (или writev()) один раз, когда будете готовы к отправке; не вызывайте write () повторно с небольшими нагрузками, потому что это будет медленно.

Ситуации, подобные вашей, именно поэтому позволяют отключить Nagle.

Комментарии:

1. Я согласен. Отключение Nagle намного лучше, чем выполнение кучи дополнительных трехсторонних рукопожатий плюс дополнительные пакеты FIN.

Ответ №2:

@Nemo дал отличный совет по TCP.

Но я предлагаю вам вместо этого посмотреть на UDP. TCP может вводить произвольную задержку при потере пакета, и «справедливость TCP» работает на основе принудительной потери пакетов. Это не идеально для передач с низкой задержкой. Желание отключить Nagle является явным признаком того, что вы используете неправильный протокол.

Комментарии:

1. Такова была моя первоначальная реакция, но ограничение, которое оттолкнуло меня от UDP, — это интеграция данных. Данные должны поступать по порядку и исправляться … другими словами, приложение не будет иметь смысла.

2. @Armando: Если вы хотите своевременно и корректно, ваш выбор, похоже, FEC. Простого «отправить несколько копий каждого пакета» должно быть достаточно. С порядковыми номерами вы можете удалить дубликаты и обеспечить правильный порядок. Если несколько копий каждого пакета будут расходовать слишком много пропускной способности, вы можете использовать некоторый код для исправления ошибок, из которых parity является самым простым (обратите внимание, запускайте его по пакетам, поскольку весь пакет, скорее всего, уйдет сразу).

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

4. @MSalters: Это именно та идея. Хотя, поскольку UDP уже имеет код обнаружения ошибок, промежуточные маршрутизаторы, скорее всего, обнаружат ошибки и отбросят весь пакет. Итак, здесь это исправление прямого удаления . Однако коды, которые обладают хорошей производительностью для исправления ошибок, также обладают высокой производительностью восстановления при стирании.