Есть ли способ сказать ОС отбросить буферизованные исходящие данные TCP? - PullRequest
1 голос
/ 01 февраля 2011

В моем клиентском программном обеспечении на основе TCP возникла забавная / раздражающая ситуация, и она выглядит следующим образом:

  1. мой клиентский процесс работает на ноутбуке и подключен через TCPна мой серверный процесс (который выполняется на другом компьютере через локальную сеть)
  2. безответственный пользователь вытаскивает кабель Ethernet из своего ноутбука, пока клиент передает данные TCP
  3. клиентский процесс продолжает вызывать send ()с некоторыми дополнительными данными TCP, заполняя буфер SO_SNDBUF ОС, пока ...
  4. клиентский процесс не уведомляется (через функцию SCDynamicStoreCallback MacOS / X), что интерфейс Ethernet не работает, и отвечает, вызывая close ()на своем сокете TCP
  5. проходит от двух до пяти секунд ...
  6. пользователь подключает кабель Ethernet обратно к
  7. , клиентский процесс получает уведомление о резервном копировании интерфейса, иавтоматически подключается к серверу

Это все работает довольно хорошо ... за исключением того, что часто есть также нежелательный шаг 8, которыйэто:

.8.Сокет TCP, который был close () d на шаге 4, восстанавливает (!) И отправляет оставшуюся часть данных, которые были в буфере исходящих данных ядра для этого сокета.Это происходит потому, что ОС пытается доставить все исходящие данные TCP до освобождения сокета ... обычно это хорошо, но в этом случае я бы предпочел, чтобы этого не произошло.

Итак,Вопрос в том, есть ли способ сказать уровню TCP отбросить данные в его SO_SNDBUF?Если это так, я мог бы сделать этот вызов непосредственно перед close () - с помощью мертвого сокета на шаге 4, и мне не пришлось бы беспокоиться о том, что данные зомби из старого сокета поступят на сервер после того, как старый сокет был оставлен.

Ответы [ 2 ]

1 голос
/ 01 февраля 2011

Это (данные, полученные из двух разных TCP-соединений, не упорядочены относительно друг друга) является фундаментальным свойством TCP / IP. Вы не должны пытаться обойти это, очистив буфер отправки - это хрупко. Вместо этого вы должны исправить приложение, чтобы обработать эту возможность на уровне приложения.

Например, если вы получаете новое соединение на стороне сервера от клиента, который, по вашему мнению, уже подключен, вам, вероятно, следует сбросить существующее соединение.

Кроме того, шаг 4 процесса немного сомнителен. На самом деле, вам просто нужно подождать, пока TCP не сообщит об ошибке (или в соединении возникнет таймаут на уровне приложения) - как вы заметили, TCP восстановится, если физическое отключение будет только кратким.

0 голосов
/ 01 февраля 2011

Если вы хотите отбросить любые данные, ожидающие передачи, когда вы закрываете сокет на шаге 4, просто установите SO_LINGER в 0, прежде чем закрывать.

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