Назад | Перейти на главную страницу

Должен ли исходный порт TCP быть уникальным для каждого хоста?

Я узнал, что TCP-соединение идентифицируется кортежем (исходный IP-адрес, исходный порт, целевой IP-адрес, порт назначения). Теоретически, таким образом, должно быть возможно подключение клиента с хоста host1: port1 к server1: port1 и в то же время другого клиента (работающего на host1) с host1: port1 на server2: port1.

Я немного тестировал на Java, и пока это кажется возможным.

Однако я несколько раз читал, что исходный порт должен быть уникальным для адреса хоста, что в основном означает, что существует жесткое ограничение не более 65536 одновременных исходящих TCP-соединений. Это правда?

Обновление: вот мой код Java. Кажется, это работает, и netstat -t ясно показывает два активные исходящие соединения с порта 9990 (один на 9997, один на 9998). По крайней мере, на современном линуксе это кажется возможным?

Socket s1 = new Socket();
s1.setReuseAddress(true);
SocketAddress saremote = new InetSocketAddress("localhost",9999);
SocketAddress salocal = new InetSocketAddress("localhost",9990);
s1.bind(salocal);
s1.connect(saremote);


Socket s2 = new Socket();
s2.setReuseAddress(true);
SocketAddress saremote2 = new InetSocketAddress("localhost",9998);
SocketAddress salocal2 = new InetSocketAddress("localhost",9990);
s2.bind(salocal2);
s2.connect(saremote2);

И вывод netstat -t (усеченный):

tcp6       0      0 localhost:9990          localhost:9998          CONNECTED 
tcp6       0      0 localhost:9990          localhost:9999          CONNECTED 

Это не требование TCP. Что касается TCP, уникальной должна быть только комбинация IP-адреса источника, порта источника, IP-адреса назначения и порта назначения. Однако на практике большинство API-интерфейсов TCP не позволяют создать более одного соединения с одним и тем же исходным портом, если только они не имеют разных исходных IP-адресов.

Это максимум, на практике он обычно ниже. Например, Linux использует net.ipv4.ip_local_port параметр ядра для определения портов, которые используются для исходящих подключений. Обычно это что-то вроде

sysctl net.ipv4.ip_local_port_range 32768 to 61000

Вы можете увеличить количество доступных с помощью sysctl, например.

sysctl -w net.ipv4.ip_local_port_range="10000 64000"

или вы можете отредактировать /etc/sysctl.conf с той же информацией

net.ipv4.ip_local_port_range = 10000 65535

Все найденные мною примеры также показывают, что минимальное значение равно 1024.

В дополнение к ответу Иэна (см. Выше), для исходящих подключений вашим ядром может быть разрешено только 10 000 портов, теоретически вы, по крайней мере, ограничены одним набором портов XX, XXX на IP-адрес адаптера. Поскольку 127.1 недоступен для внешнего мира, находясь в локальной сети, то для каждого другой IP-адрес (внешний ) у вас есть набор исходящих портов в пределах диапазона портов 65K.

Итак, исходящий лимит действительно:

  With 1 IP Address: XX,XXX (or 2 x XX,XXX on internal network)
  With 2 IP addresses: 2 x XX,XXX (or 3 x XX,XXX on internal network)
  With 3 IP addresses: 3 x XX,XXX (or 4 x XX,XXX on internal network)
  etc.

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

Да. Это верно.

Порты для привязки, а приложения к сети.

У вас не может быть более 65553 приложений, подключенных по TCP, и 65535, подключенных по UDP на одном хосте. Операционные системы обычно динамически управляли портами, назначая по одному для каждого приложения, которое подключается к сети.

Если у вас есть два приложения, которые прослушивают один и тот же порт, когда приходит сетевой пакет, компьютер не может знать, какое приложение будет доставить данные. Например, если у вас есть Messenger и Skype, привязанные к одному порту, ваше сообщение будет отображаться в Skype и наоборот :)

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