Резюме
Сокет TCP - это конечная точка экземпляр , определяемый IP-адресом и портом в контексте определенного соединения TCP или состояния прослушивания.
Порт - это идентификатор виртуализации , определяющий конечную точку службы (в отличие от экземпляр конечная точка, или идентификатор сеанса).
TCP-сокет не соединение , это конечная точка определенного соединения.
Возможны одновременные соединения с конечной точкой службы , поскольку соединение идентифицируется как его локальной, так и удаленной конечными точками, что позволяет маршрутизировать трафик в конкретный экземпляр службы.
Для данной комбинации адреса / порта может быть только один сокет прослушивателя .
Exposition
Это был интересный вопрос, который заставил меня пересмотреть ряд вещей, которые, как я думал, я знал наизнанку. Вы могли бы подумать, что имя типа «сокет» было бы само собой разумеющимся: оно, очевидно, было выбрано, чтобы вызывать образы конечной точки, в которую вы подключаете сетевой кабель, при этом существуют сильные функциональные параллели. Тем не менее, на языке сети слово «розетка» несет в себе столько багажа, что необходим тщательный повторный осмотр.
В самом широком смысле порт является точкой входа или выхода. Хотя французское слово porte не используется в контексте сети, оно буквально означает дверь или шлюз , что еще раз подчеркивает тот факт, что порты являются конечными точками транспортировки, независимо от того, отправляете вы данные или большие стальные контейнеры.
Для целей этого обсуждения я ограничусь рассмотрением контекста сетей TCP-IP. Модель OSI все очень хорошо, но никогда не была полностью реализована, и гораздо менее широко развернута в условиях высокой нагрузки.
Комбинация IP-адреса и порта строго известна как конечная точка и иногда называется сокетом. Это использование происходит с RFC793, оригинальной спецификации TCP.
TCP соединение определяется двумя конечными точками, известными как сокеты .
Конечная точка (сокет) определяется комбинацией сетевого адреса и идентификатора port . Обратите внимание, что адрес / порт не полностью идентифицирует сокет (подробнее об этом позже).
Назначение портов - дифференцировать несколько конечных точек на данном сетевом адресе. Можно сказать, что порт является виртуальной конечной точкой. Эта виртуализация делает возможным одновременное подключение нескольких соединений к одному сетевому интерфейсу.
Это сокет пара (4-х кортеж
состоящий из IP-адреса клиента,
номер порта клиента, IP-адрес сервера,
и номер порта сервера), который указывает
две конечные точки, которые уникально
идентифицирует каждое TCP-соединение в
интернет. ( TCP-IP Illustrated Volume 1 , W. Richard Stevens)
В большинстве языков, производных от C, TCP-соединения устанавливаются и управляются с использованием методов в экземпляре класса Socket. Хотя обычно работает на более высоком уровне абстракции, обычно это экземпляр класса NetworkStream, обычно это предоставляет ссылку на объект сокета. Кодеру этот объект сокета, по-видимому, представляет соединение, поскольку соединение создается и управляется с использованием методов объекта сокета.
В C # для установки TCP-соединения (с существующим слушателем) сначала вы создаете TcpClient . Если вы не указываете конечную точку для конструктора TcpClient , она использует значения по умолчанию - так или иначе, определяется локальная конечная точка. Затем вы вызываете Connect
метод в экземпляре, который вы создали. Этот метод требует параметр, описывающий другую конечную точку.
Все это немного сбивает с толку и наводит вас на мысль, что сокет - это соединение, которое является бредом. Я работал над этим заблуждением, пока Ричард Дорман не задал вопрос.
После долгих чтений и размышлений я убежден, что было бы гораздо разумнее иметь класс TcpConnection с конструктором, который принимает два аргумента, LocalEndpoint и RemoteEndpoint . Возможно, вы могли бы поддерживать один аргумент RemoteEndpoint , когда для локальной конечной точки допустимы значения по умолчанию. Это неоднозначно на многосетевых компьютерах, но неоднозначность может быть решена с помощью таблицы маршрутизации путем выбора интерфейса с кратчайшим маршрутом к удаленной конечной точке.
Ясность будет улучшена и в других отношениях. Сокет не определяется комбинацией IP-адреса и порта:
[...] TCP демультиплексирует входящие сегменты, используя все четыре значения, которые включают локальные и внешние адреса: IP-адрес назначения, номер порта назначения, IP-адрес источника и номер порта источника. TCP не может определить, какой процесс получает входящий сегмент, глядя только на порт назначения. Кроме того, единственная из [различных] конечных точек в [заданном номере порта], которая будет принимать входящие запросы на соединение, - это та, которая находится в состоянии прослушивания. (p255, Иллюстрированный том TCP-IP, 1 , У. Ричард Стивенс)
Как вы можете видеть, сетевая служба может не просто иметь, а иметь множество сокетов с одним и тем же адресом / портом, но только один сокет прослушивателя для конкретной комбинации адрес / порт. Типичные реализации библиотеки представляют класс сокетов, экземпляр которого используется для создания и управления соединением. Это крайне неудачно, поскольку вызывает путаницу и приводит к широко распространенному слиянию этих двух понятий.
Хагравал мне не верит (см. Комментарии), так что вот реальный пример. Я подключил веб-браузер к http://dilbert.com, а затем запустил netstat -an -p tcp
. Последние шесть строк вывода содержат два примера того, что адреса и порта недостаточно для однозначной идентификации сокета. Между 192.168.1.3 (моя рабочая станция) и 54.252.94.236:80 (удаленный HTTP-сервер) существует два различных соединения
TCP 192.168.1.3:63240 54.252.94.236:80 SYN_SENT
TCP 192.168.1.3:63241 54.252.94.236:80 SYN_SENT
TCP 192.168.1.3:63242 207.38.110.62:80 SYN_SENT
TCP 192.168.1.3:63243 207.38.110.62:80 SYN_SENT
TCP 192.168.1.3:64161 65.54.225.168:443 ESTABLISHED
Поскольку сокет является конечной точкой соединения, есть два сокета с комбинацией адрес / порт 207.38.110.62:80
и еще два с комбинацией адрес / порт 54.252.94.236:80
.
Я думаю, что неправильное понимание Хагравала проистекает из моего очень осторожного использования слова «идентифицирует». Я имею в виду «полностью, однозначно и однозначно идентифицирует». В приведенном выше примере есть две конечные точки с комбинацией адрес / порт 54.252.94.236:80
. Если у вас есть только адрес и порт, у вас недостаточно информации, чтобы разделить эти сокеты. Недостаточно информации для идентификации сокета.
Добавление
Второй абзац раздела 2.7 RFC793 гласит
Соединение полностью определяется парой розеток на концах.
локальный сокет может участвовать во многих подключениях к разным
Розетки.
Это определение сокета бесполезно с точки зрения программирования, поскольку оно не совпадает с сокетом объект , который является конечной точкой конкретного соединения. Для программиста, и большая часть аудитории этого вопроса - программисты, это жизненно важное функциональное отличие.
Ссылки
Иллюстрированный том TCP-IP 1 Протоколы , В. Ричард Стивенс, 1994 Эддисон Уэсли
RFC793 , Институт информационных наук, Университет Южной Калифорнии для DARPA
RFC147 , Определение гнезда, Джоэл М. Винетт, Лаборатория Линкольна