Как работает функция socket API accept ()?


API сокета является де-факто стандартом для TCP/IP и UDP / IP связи (то есть, сетевой код, как мы его знаем). Однако, одна из его основных функций,accept() Это немного волшебно.

заимствовать полуформальное определение:

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

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

как accept работы? Как это реализуется? Существует много путаницы на эту тему. Многие люди утверждают, что принимают открывает новый порт и вы общаетесь с клиентом через него. Но это, очевидно, не так, как нет открывается новый порт. Вы действительно можете общаться через один и тот же порт с разными клиентами, но как? Когда несколько потоков вызывают recv на том же порту, как данные знают, куда идти?

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

было бы здорово получить подробное объяснение внутренней работы этот механизм.

4 99

4 ответа:

ваша путаница заключается в том, что сокет идентифицируется по IP сервера : порт сервера. Когда в действительности сокеты однозначно идентифицируются квартетом информации:

Client IP : Client Port и Server IP : Server Port

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

пример для уточнения вещей:

скажем, у нас есть сервер в 192.168.1.1: 80 и два клиента, 10.0.0.1 и 10.0.0.2.

10.0.0.1 открывает соединение на локальном порту 1234 и подключается к серверу. Теперь у сервера есть один сокет, идентифицированный следующим образом:

10.0.0.1:1234 - 192.168.1.1:80

теперь 10.0.0.2 открывает соединение на локальном порту 5678 и подключается к серверу. Теперь сервер имеет два сокета, идентифицированных следующим образом:

10.0.0.1:1234 - 192.168.1.1:80
10.0.0.2:5678 - 192.168.1.1:80

просто добавить к ответу, данному пользователем "17 из 26"

гнездо на самом деле состоит из 5 кортежей - (IP-адрес источника, порт источника, IP назначения, порт назначения, протокол). Здесь протокол может быть TCP или UDP или любой протокол транспортного уровня. Этот протокол идентифицируется в пакете из поля "протокол" в датаграмме IP.

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

Apache на стороне сервера говорить дальше (server1. com:880-client1:1234 на TCP) и World of Warcraft talking on (server1.com:880-client1:1234 on UDP)

и клиент, и сервер будут обрабатывать это как поле протокола в IP-пакете в обоих случаях отличается, даже если все остальные 4 поля одинаковы.

что смутило меня, когда я учился этому, было то, что термины socket и port предположим, что они являются чем-то физическим, когда на самом деле это просто структуры данных, которые ядро использует для абстрагирования деталей сети.

таким образом, структуры данных реализованы, чтобы иметь возможность поддерживать отдельные соединения от разных клиентов. Что касается как они реализованы, ответ либо a.) это не имеет значения, цель API сокетов именно в этом реализация не должна иметь значения или b.) просто посмотрите. Помимо настоятельно рекомендуемых книг Стивенса, содержащих подробное описание одной реализации, проверьте источник в Linux или Solaris или один из BSD.

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

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

в первые дни ARPAnet некоторые протоколы (FTP для одного) будут прослушивать указанный порт для запросов на подключение и отвечать портом передачи обслуживания. Дальнейшие коммуникации для этого соединения будут проходить через порт передачи. Это было сделано для повышения производительности каждого пакета: компьютеры были несколько порядков магнитуда в те дни была меньше.