TCP: что происходит, когда клиент подключается, отправляет данные и отключается до принятия

Я тестирую код на C и обнаружил странное поведение с вызовами сокетов TCP.

  1. Я определил один поток прослушивания, который принимает клиентов синхронно, и после принятия клиента он обрабатывает его в цикле for, пока он не отключится. Таким образом, одновременно обрабатывается только один клиент. Так я звонюaccept в петле, а затемrecv во внутреннем цикле, пока не будет получен пустой буфер.

  2. Запускаю 5 потоков с клиентами, звонюconnect ,send и наконецclose

  3. Я не получаю ошибок ни при каких звонках. Вроде все нормально.

Однако, когда я печатаю полученное сообщение на стороне сервера, оказывается, что только первый клиент прошел к серверу, т.е.accept никогда не срабатывает на других клиентах.

Итак, мои вопросы:

  1. Не долженconnect подождите, пока сервер не позвонитaccept ? Или уровень ядра заботится о буферизации под капотом?
  2. Если это не так, то не должен ли сервер в любом случае принимать сокет, даже если он находится в отключенном состоянии? Я имею в виду, ожидается ли потеря всех входящих данных?
  3. Или мне следует предположить, что в моем коде есть ошибка?
# sockets tcp
Источник
  • 0
    Помните второй аргумент для listen(int fd, int backlog) ? Все трехстороннее рукопожатие завершается (стеком TCP) до того, как accept() доставит fd на сервер в пользовательском пространстве. Итак: сокеты находятся в подключенном состоянии, но пользовательский процесс еще не подобрал их (вызвав accept() )
  • 0
    @joop Верно. Я получаю это сейчас. Итак, данные были помещены в буфер. Причина, по которой я не видел вывода, заключалась в том, что я случайно заблокировал сервер. Так что да, спасибо за ответ на мой вопрос 1. Я уже знаю ответ 2.
  • 0
    @joop Вы можете написать это как ответ, чтобы я мог принять его.
Codelisting
за 1 против
Лучший ответ

Конечный автомат TCP исполняет синхронизированный танец с конечным автоматом клиента. Все это выполняется на уровне ОС ( стек TCP / IP); только процесс пользовательского пространства может делать некоторые системные вызовы, чтобы время от времени влиять на этот механизм. Как только клиент позвонитlisten() эта машина запущена; и будут установлены новые связи.

Помните второй аргумент в пользуlisten(int fd, int backlog) ? Все трехстороннее рукопожатие завершается (стеком TCP) доaccept() доставляет fd на сервер в пользовательском пространстве. Итак: сокеты находятся в подключенном состоянии, но пользовательский процесс еще не взял их (вызвавaccept() )

Не звонитaccept() вызовет постановку новых соединений в очередь ядром. Эти соединения полностью функциональны, но очевидно, что буферы данных могут заполниться, и соединение будет ограничено.

Рекомендуемая литература: Comer & Stevens: Межсетевое взаимодействие с TCP / IP 10.6-10.7 (содержащее диаграмму состояний TCP)

Codelisting
Популярные категории
На заметку программисту