Получение данных из уже закрытого сокета?
Предположим, у меня есть серверное приложение-соединение через TCP, используя сокеты UNIX.
соединение асинхронно - другими словами, сокеты клиентов и серверов не блокируются.
предположим следующую ситуацию: в некоторых условиях сервер может решить отправить некоторые данные подключенному клиенту и немедленно закрыть соединение: используя shutdown
с SHUT_RDWR
.
Итак, мой вопрос-гарантируется ли, что при вызове клиента recv
, он получит (отправленные сервером) данные?
или, чтобы получить данные, recv
должен быть вызван перед shutdown
? Если да, то что мне делать (или, точнее, как это сделать), чтобы убедиться, что данные получены клиентом?
3 ответов
вы можете управлять этим поведением с помощью " setsockopt (SO_LINGER)":
SO_LINGER Ожидает завершения функции close, если данные присутствуют. Если этот параметр включен и при закрытии присутствуют неотправленные данные вызывается функция, вызывающее приложение блокируется во время закройте функцию до тех пор, пока данные не будут переданы или соединение не будет истекло время. Функция close возвращает без блокирует звонящего. Этот параметр имеет значение только для сокетов stream.
Читайте также:
нет никакой гарантии, что вы получите какие-либо данные, не говоря уже об этих данных, но данные, ожидающие закрытия сокета, подлежат же гарантирует, как и все другие данные: если он прибудет, он прибудет в порядке и неповрежденным и при условии лучших усилий TCP.
NB "асинхронный" и "неблокирующий" -это две разные вещи, а не два термина для одного и того же.
после того, как вы успешно записали данные в сокет, он находится в буфере ядра, где он будет оставаться до тех пор, пока он не будет отправлен и подтвержден. Завершение работы не приводит к потере буферизованных данных. Закрытие сокета не приводит к потере буферизованных данных. Даже смерть процесса отправки не приведет к потере буферизованных данных.
вы можете наблюдать размер буфера с netstat
. Столбец SendQ, сколько данных ядра еще хочет передавать.
после того, как клиент подтвердил все, порт исчезает с сервера. Это может произойти до того, как клиент прочитает данные, и в этом случае это будет в RecvQ на клиенте. В принципе вам не о чем беспокоиться. После успешной записи в TCP-сокет каждый компонент изо всех сил пытается убедиться, что ваши данные попадают в пункт назначения невредимыми, независимо от того, что происходит с отправляющим сокетом и/или процессом.