Это может быть очень простой вопрос, но он меня смущает.
Могут ли два разных подключенных сокета использовать общий порт? Я пишу сервер приложений, который должен иметь возможность обрабатывать более 100 тысяч одновременных подключений, и мы знаем, что количество портов, доступных в системе, составляет около 60 тысяч (16 бит). Подключенный сокет назначается новому (выделенному) порту, поэтому это означает, что количество одновременных подключений ограничено количеством портов, если только несколько сокетов не могут использовать один и тот же порт. Итак, вопрос.
Спасибо за помощь в продвижении!
Прослушивание TCP / HTTP на портах: как многие пользователи могут использовать один и тот же порт
Итак, что происходит, когда сервер прослушивает входящие соединения через порт TCP? Например, предположим, что у вас есть веб-сервер на порту 80. Предположим, что ваш компьютер имеет общедоступный IP-адрес 24.14.181.229, а у человека, который пытается подключиться к вам, есть IP-адрес 10.1.2.3. Этот человек может подключиться к вам, открыв TCP-сокет на 24.14.181.229:80. Достаточно просто.
Интуитивно (и ошибочно) большинство людей предполагает, что это выглядит примерно так:
Это интуитивно понятно, поскольку с точки зрения клиента у него есть IP-адрес, и он подключается к серверу по IP: PORT. Поскольку клиент подключается к порту 80, то его порт тоже должен быть 80? Это разумная мысль, но на самом деле не то, что происходит. Если бы это было правильно, мы могли бы обслуживать только одного пользователя на внешний IP-адрес. Как только удаленный компьютер подключится, он будет подключать порт 80 к порту 80, и никто другой не сможет подключиться.
Следует понимать три вещи:
1.) На сервере процесс прослушивает порт. Как только он получает соединение, он передает его другому потоку. Связь никогда не забивает порт прослушивания.
2.) Соединения однозначно идентифицируются операционной системой с помощью следующих пяти кортежей: (локальный IP, локальный порт, удаленный IP, удаленный порт, протокол). Если какой-либо элемент в кортеже отличается, то это полностью независимое соединение.
3.) Когда клиент подключается к серверу, он выбирает случайный неиспользуемый порт источника высокого порядка . Таким образом, один клиент может иметь до ~ 64k подключений к серверу для одного и того же порта назначения.
Итак, это действительно то, что создается, когда клиент подключается к серверу:
Глядя на то, что происходит на самом деле
Во-первых, давайте с помощью netstat посмотрим, что происходит на этом компьютере. Мы будем использовать порт 500 вместо 80 (потому что на порте 80 происходит много всего, так как это общий порт, но функционально это не имеет значения).
Как и ожидалось, вывод пустой. Теперь запустим веб-сервер:
Теперь вот результат повторного запуска netstat:
Итак, теперь есть один процесс, который активно прослушивает (Состояние: LISTEN) порт 500. Локальный адрес - 0.0.0.0, что является кодом для "прослушивания всех IP-адресов". Легкая ошибка - слушать только порт 127.0.0.1, который будет принимать соединения только с текущего компьютера. Так что это не соединение, это просто означает, что процесс запросил привязку () к IP-адресу порта, и этот процесс отвечает за обработку всех подключений к этому порту. Это намекает на ограничение, согласно которому на каждом компьютере может быть только один процесс, прослушивающий порт (есть способы обойти это с помощью мультиплексирования, но это гораздо более сложная тема). Если веб-сервер прослушивает порт 80, он не может использовать этот порт для других веб-серверов.
Итак, теперь давайте подключим пользователя к нашей машине:
Это простой скрипт ( https://github.com/grokit/quickweb ), который открывает сокет TCP, отправляет полезные данные (в данном случае «Тестовые данные»), ждет несколько секунд и отключается. Повторное выполнение netstat во время этого процесса отображает следующее:
Если вы подключитесь к другому клиенту и снова выполните netstat, вы увидите следующее:
... то есть клиент использовал другой случайный порт для соединения. Таким образом, между IP-адресами никогда не бывает путаницы.
источник
Это обычная интуиция, но она неверна. Подключенный сокет не назначается новому / выделенному порту. Единственное фактическое ограничение, которому должен удовлетворять стек TCP, - это то, что кортеж (local_address, local_port, remote_address, remote_port) должен быть уникальным для каждого соединения сокета. Таким образом, на сервере может быть много сокетов TCP, использующих один и тот же локальный порт, если каждый из сокетов порта подключен к другому удаленному месту.
См. Параграф «Пара сокетов» на странице http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false.
источник
bind()
операция предшествуетconnect()
операции, даже неявно.bind()
он используется только на стороне сервера.accept()?
Значит, клиентская сторона также привяжет конкретный порт?bind()
можно было использовать на стороне клиентаconnect()
.Теоретически да. Практика, нет. Большинство ядер (включая linux) не позволяют использовать второй
bind()
порт после уже выделенного. Это было не так уж и сложно.По идее, мы должны различать сокет и порт . Сокеты - это конечные точки двунаправленной связи, то есть «вещи», куда мы можем отправлять и получать байты. Это концептуальная вещь, такого поля в заголовке пакета с именем «сокет» нет.
Порт - это идентификатор, позволяющий идентифицировать сокет. В случае TCP порт - это 16-битное целое число, но есть и другие протоколы (например, в сокетах unix «порт» по сути представляет собой строку).
Основная проблема заключается в следующем: если приходит входящий пакет, ядро может идентифицировать свой сокет по номеру порта назначения. Это наиболее распространенный способ, но не единственный:
Поскольку вы работаете на сервере приложений, он сможет это сделать.
источник
bind()
.bind()
? Я могу себе это представить, да, это вполне возможно, но факт в том, что и WinSock, и API Posix используютbind()
для этого вызов, даже их параметризация практически одинакова. Даже если у API нет этого вызова, вам нужно как-то сказать это, откуда вы хотите читать входящие байты .listen()
/accept()
API могут создавать сокеты таким образом, чтобы ядро различало их по входящим портам. Вопрос о OP можно интерпретировать так, как он этого требует. Думаю, это вполне реально, но не об этом буквально означает его вопрос.Нет. Невозможно использовать один и тот же порт в определенный момент. Но вы можете сделать свое приложение таким, чтобы оно осуществляло доступ к порту в разное время.
источник