TCP: могут ли два разных сокета совместно использовать порт?


Это может быть очень простой вопрос, но он меня смущает.

могут ли два разных подключенных сокета совместно использовать порт? Я пишу сервер приложений, который должен иметь возможность обрабатывать более 100 тыс. параллельных подключений, и мы знаем, что количество доступных портов в системе составляет около 60 тыс. (16 бит). Подключенный сокет присваивается новый (выделенный) порт, так что это означает, что количество одновременных подключений ограничено количеством портов, если несколько розеток, может используйте один и тот же порт. Итак, вопрос.

Спасибо за помощь заранее!

4 66

4 ответа:

A сервер сокет слушает на одном порту. Все установленные клиентские соединения на этом сервере связаны с тем же самым портом прослушивания на стороне сервера подключение. Установленное соединение однозначно идентифицируется комбинацией пар IP/порт на стороне клиента и сервера. Несколько соединений на одном сервере могут совместно использовать один и тот же на стороне сервера пара IP/Port, если они связаны с разными на стороне клиента пары IP/Port, и сервер сможет обрабатывать столько клиентов, сколько позволяют доступные системные ресурсы.

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

TCP / HTTP прослушивание портов: как многие пользователи могут использовать один и тот же порт

Итак, что происходит, когда сервер прослушивает входящие соединения на TCP-порт? Например, скажем, у вас есть веб-сервер на порту 80. Предположим, что ваш компьютер имеет общедоступный IP-адрес 24.14.181.229, а человек, который пытается подключиться к вам, имеет IP-адрес 10.1.2.3. Этот человек может подключиться к вам, открыв TCP-сокет до 24.14.181.229:80. Достаточно просто.

интуитивно (и ошибочно), большинство людей предполагают, что это выглядит примерно так:

    Local Computer    | Remote Computer
    --------------------------------
    <local_ip>:80     | <foreign_ip>:80

    ^^ not actually what happens, but this is the conceptual model a lot of people have in mind.

это интуитивно, потому что с точки зрения клиента, он имеет IP-адрес и подключается к серверу по IP:порт. Поскольку клиент подключается к порту 80, то его порт тоже должен быть 80? Это разумная вещь, чтобы думать, но на самом деле не происходит. Если бы это было правильно, мы могли бы обслуживать только одного пользователя на иностранный IP-адрес. После того, как удаленный компьютер подключается, то он будет Хог порт 80 подключение к порту 80, и никто не мог подключиться.

три вещи должны быть поняты:

1.) На сервере, процесс слушать на порт. Как только он получает соединение, он передает его другому потоку. Связь никогда не засоряет порт прослушивания.

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

3.) Когда клиент подключается к серверу, он выбирает случайный, неиспользуемый порт источника высокого порядка. Таким образом, один клиент может иметь до ~64k подключений к серверу для одного и того же порта назначения.

Итак, это действительно то, что создается, когда клиент подключается к серверу:

    Local Computer   | Remote Computer           | Role
    -----------------------------------------------------------
    0.0.0.0:80       | <none>                    | LISTENING
    127.0.0.1:80     | 10.1.2.3:<random_port>    | ESTABLISHED

глядя на то, что на самом деле происходит

во-первых, давайте использовать netstat, чтобы увидеть что происходит на этом компьютере. Мы будем использовать порт 500 вместо 80 (потому что вся куча вещей происходит на порту 80, поскольку это общий порт, но функционально это не имеет значения).

    netstat -atnp | grep -i ":500 "

как и ожидалось, выход пуст. Теперь давайте запустим веб-сервер:

    sudo python3 -m http.server 500

теперь, вот результат запуска netstat снова:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      - 

Итак, теперь есть один процесс, который активно слушает (состояние: слушать) на порту 500. Местный житель адрес 0.0.0.0, который является кодом для "прослушивания всех ip-адресов". Простая ошибка заключается в прослушивании только порта 127.0.0.1, который будет принимать только соединения с текущего компьютера. Таким образом, это не соединение, это просто означает, что процесс запросил привязку() к порту IP, и этот процесс отвечает за обработку всех подключений к этому порту. Это намекает на ограничение, что может быть только один процесс на компьютер, прослушивающий порт (есть способы обойти это использование мультиплексирования, но это гораздо более сложная тема). Если веб-сервер прослушивает порт 80, он не может совместно использовать этот порт с другими веб-серверами.

Итак, теперь давайте подключим пользователя к нашей машине:

    quicknet -m tcp -t localhost:500 -p Test payload.

это простой скрипт (https://github.com/grokit/quickweb), который открывает TCP-сокет, отправляет полезную нагрузку ("тестовая полезная нагрузка."в данном случае), ждет несколько секунд и отключается. Выполнение netstat снова, пока это происходит отображает следующее:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:54240      ESTABLISHED -

если вы подключитесь к другому клиенту и снова выполните netstat, вы увидите следующее:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:26813      ESTABLISHED -

... то есть, клиент использовал другой случайный порт для подключения. Таким образом, никогда не бывает путаницы между 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

Теоретически, да. Практика, нет. Большинство ядер (ВКЛ. linux) не позволяет вам второй bind() к уже выделенному порту. Это был не очень большой патч, чтобы сделать это разрешено.

концептуально, мы должны различать между гнездо и порт. Сокеты-это конечные точки двунаправленной связи, т. е. "вещи", где мы можем отправлять и получать байты. Это концептуальная вещь, нет такого поля в заголовке пакета с именем "розетка."

порт-это идентификатор, который способен определить сокет. В случае TCP порт является 16-битным целым числом, но есть и другие протоколы (например, в сокетах unix "порт" по существу является строкой).

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

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

потому что вы работаете на сервере приложений, оно сможет сделать что.