Как закрытие сокета влияет на чтение другой стороны

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

Укажите операционную систему и интерфейс сокетов.

Lightness Races in Orbit 30.05.2019 15:42

Какое отношение сокеты имеют к C++ или C? Сокеты — это интерфейс, к которому можно получить доступ, независимо от языка.

Thomas Matthews 30.05.2019 16:06

@ThomasMatthews Мой проект на C, поэтому я отметил C/C++, я не знал, работают ли сокеты по-другому на других языках

Konstantinos Kyriakos 30.05.2019 18:51

Кстати, C - это другой язык, чем C++. Например, в C++ есть шаблоны и std::string. В языке C есть массивы символов, и у вас может быть переменная с именем «класс». Нет такого языка, как C/C++.

Thomas Matthews 30.05.2019 23:10

Насколько я понимаю, код сокета будет вести себя одинаково независимо от того, используете ли вы Java, Fortran или Visual Basic.

Thomas Matthews 30.05.2019 23:11

@ThomasMatthews C и C++ имеют общие библиотеки для сокетов

Konstantinos Kyriakos 31.05.2019 03:46
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
6
490
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

«Если сервер напишет сообщение в сокете, а затем закроет его до того, как клиент прочитает. Сможет ли клиент прочитать сообщение?»

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

Предполагая, что сервер изящно закрывает сокет, чтобы вообще создать FIN, то есть

Remy Lebeau 30.05.2019 16:57

@RemyLebeau Конечно. Если серверный процесс дает сбой или просто exits, или ОС на любом конце имеет ошибку, или кто-то выдергивает сетевой кабель, или испаряется достаточная промежуточная сетевая инфраструктура. И т. д. Тогда никто не может сделать никаких разумных предположений о том, что произойдет.

Jesper Juhl 30.05.2019 17:03

Что, если FIN опережает данные и первым достигает клиента/сервера. Гарантировано ли, что он все еще сможет читать?

user10957435 30.05.2019 18:21

@Chipster все TCP-пакеты имеют порядковый номер. Сетевой стек (обычно реализованный в ядре ОС) отвечает за доставку пакетов в приложение по порядку и задерживает доставку или запрашивает повторную передачу пакетов в зависимости от ситуации. С точки зрения приложений TCP-соединение представляет собой упорядоченный поток байтов, и оно никогда не увидит, что что-то поступает не по порядку. С UDP все иначе.

Jesper Juhl 30.05.2019 18:27

Это поведение зависит от реализации, в общем, вы не должны предполагать, что клиент может прочитать сообщение, close(2) в руководстве по Linux говорится:

Be sure to use shutdown(2) to shut down all parts the connection before closing the socket.

Если вы хотите убедиться, что клиент прочитал это сообщение, сделайте так, чтобы этот клиент подтвердил это действие в протоколе вашего приложения.

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

«Когда вы отправляете данные через сокет, а затем закрываете тот же сокет, нет никакой гарантии, что ядро ​​​​опустошило свои внутренние буферы в сеть» — нет, вы этого не знаете. Но это буду сделать. Он не просто отбрасывает невыполненные данные при закрытии.

Jesper Juhl 30.05.2019 15:25

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

Human-Compiler 30.05.2019 15:26

Это не верно. Соединение останется внутри ядра и обеспечит опустошение буферов даже после закрытия сокета. Вы можете заблокировать свою программу на close(), ожидая завершения соединения, используя опцию SO_LINGER.

lvella 30.05.2019 15:26

Он отбросит невыполненные данные при закрытии, если не сможет их отправить, и вы получите сообщение об ошибке из close(2).

lle-bout 30.05.2019 15:27

@Bitwize Чтобы уточнить, я не хотел ссылаться на весь цитируемый блоком текст, отредактировал свой ответ.

lle-bout 30.05.2019 15:30

@LightnessRacesinOrbit Закрытие сокета не отключает поведение протокола TCP. Он будет повторять попытки до тех пор, пока не получит ACK или не сдастся, как обычно.

lvella 30.05.2019 15:33

@lvella О да: D Это не будет FIN, пока он не очистит буфер и не получит все ACKd, я полагаю

Lightness Races in Orbit 30.05.2019 15:34

@lvella Ты уверен в этом? Мне кажется, что просьба close(2) означает, что вы хотите, чтобы системные ресурсы за файловым дескриптором были очищены. Не поделитесь ссылкой на такую ​​информацию?

lle-bout 30.05.2019 15:35

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

Jesper Juhl 30.05.2019 15:36

Я бы предположил, что он освобождает ресурсы на определенном уровне, но базовый сетевой драйвер по-прежнему делает свое дело и управляет своими собственными ресурсами, как всегда.

Lightness Races in Orbit 30.05.2019 15:40

Действительно, на странице руководства конкретно сказано, что когда ваш FD представляет файл, close на самом деле не делает с файлом ничего волшебного. Вы просто закрываете ручку. Синхронизация/буферизация/и т. д. все еще происходит внизу.

Lightness Races in Orbit 30.05.2019 15:41

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

lle-bout 30.05.2019 15:41

Конечно, мы все предполагаем, что это похоже на BSD close. Я думаю, что это справедливое предположение, особенно потому, что все сокеты, которые я знаю, почти наверняка работают так.

Lightness Races in Orbit 30.05.2019 15:42

@LeoLeBouter Да, я уверен, но, к сожалению, у меня нет ссылки. Я не думаю, что это где-то указано явно, но вы можете склеить части вместе: сокеты — это интерфейс POSIX для любого типа сети, включая TCP/IP, сокеты Unix, X25 и т. д. close() является частью этого интерфейса, и отключает сокет. Изменение ожидаемого поведения TCP/IP было бы очень странным исключением для реализации.

lvella 30.05.2019 15:44

Другие вопросы по теме