S - это серверная программа: допустим, это HTTP-сервер, поэтому он использует известный номер порта для HTTP , равный 80. Я запускаю его на хосте с IP-адресом 10.0.0.4
, поэтому он будет прослушивать соединения 10.0.0.4:80
(потому что вот где все ожидают его найти).
Внутри S я собираюсь создать сокет и связать его с этим адресом: теперь ОС знает, что входящие соединения 10.0.0.4:80
должны быть направлены к моему процессу S через этот конкретный сокет.
вывод netstat, когда сокет связан:
$ netstat --tcp -lan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
NB. локальный адрес - все нули, потому что S не волнует, как его клиенты достигают его
Как только S имеет этот сокет, он будет принимать соединения - каждый раз, когда подключается новый клиент, accept
возвращает новый сокет, который является специфическим для этого клиента
вывод netstat после того, как соединение принято:
$ netstat --tcp -lan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 10.0.0.4:80 10.0.0.5:55715 ESTABLISHED
10.0.0.4:80
представляет конец соединения S и связан с сокетом, возвращаемымaccept
10.0.0.5:55715
является концом соединения клиента и связан с сокетом, который клиент передал для соединения . Порт клиента не используется ни для чего, кроме маршрутизации пакетов по этому TCP-соединению к нужному процессу: он назначается случайным образом ядром клиента из диапазона временных портов.
Теперь S может с радостью продолжать принимать больше клиентских подключений ... каждый получит свой собственный сокет, каждый сокет будет связан с уникальным TCP-соединением, и каждое соединение будет иметь уникальный удаленный адрес. S будет отслеживать состояние клиента (если оно есть), связывая его с сокетом.
Итак, примерно:
- IP-адрес для маршрутизации между хостами в сети
- порт для маршрутизации на правильный сокет на хосте
- Я почти сказал правильный процесс , но на самом деле можно иметь несколько (обычно дочерних) процессов, принимающих все в одном сокете ...
- однако каждый раз, когда
accept
возвращается один из одновременных вызовов, он делает это только в одном процессе, сокет каждого входящего соединения уникален для одного экземпляра сервера.
- сокет - это объект, который процесс использует, чтобы поговорить с ОС о конкретном соединении, как дескриптор файла
- как уже упоминалось в комментариях, существует множество других применений для сокетов, которые вообще не используют порты: например, socketpair создает пару сокетов, соединенных вместе, которые не имеют никакой схемы адресации - единственный способ использовать этот канал - это процесс, который вызвал
socketpair
, являясь дочерним элементом этого процесса и наследуя его, или явно передавая один из сокетов из этого процесса