5
$ lsof

memcached 15844 root   28u  IPv6     113604       TCP *:11051 (LISTEN)
memcached 15844 root   29u  IPv4     113605       TCP *:11051 (LISTEN)
memcached 15844 root   30u  IPv6     113609       UDP *:11051 
memcached 15844 root   31u  IPv4     113610       UDP *:11051 

Это по IP, по протоколу или по любым другим параметрам?

2 ответа2

4

Один и тот же номер порта можно использовать один раз для TCP и один раз для UDP, и каждый из них существует в IPv4 и IPv6.

Номера портов TCP и UDP - это совершенно разные номерные пространства, они просто назначаются парами, и приложениям, которым обоим обычно нужно использовать один и тот же номер.

IPv4 и IPv6 - это несколько разные протоколы; В принципе, приложение IPv6 может принимать соединения IPv4, но обычно считается хорошим стилем иметь два отдельных сокета.

3

Каждая запись в выводе netstat или lsof -i называется сокетом.

Каждая розетка сделана уникальной благодаря комбинации:

  • семейство протоколов (например, IPv4 или IPv6)
  • протокол (например, TCP или UDP)
  • местный адрес
  • местный порт
  • удаленный адрес
  • удаленный порт

Эта комбинация переменных называется кортежем соединения.

Рассмотрим ssh .

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

# netstat -tnl | grep 22
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN

Но вы также увидите записи для каждого активного соединения.

# netstat -tn
tcp        0      0 192.168.x.y:22          192.168.x.a:ppppp       ESTABLISHED
tcp        0      0 192.168.x.y:22          192.168.x.b:qqqqq       ESTABLISHED

Таким образом, вышеприведенный вывод показывает, что порт 22 используется 3 раза на одном компьютере.

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

Но он также может быть уникальным по локальному адресу или порту.

Например, вы можете использовать виртуальные хосты Apache IP для отображения другого сайта в зависимости от имени хоста или IP-адреса:

# netstat -tnlp | grep 80
tcp        0      0 1.2.3.4:80              0.0.0.0:*               LISTEN      9876/apache2
tcp        0      0 1.2.3.5:80              0.0.0.0:*               LISTEN      9876/apache2

Здесь есть два сокета, слушающих на порте 80.

В этом примере, если трафик приходит с адресом назначения 1.2.3.4, он будет доставлен в первый сокет; если пункт назначения 1.2.3.5, он переходит ко второму.

Однако сервер должен сделать это явно. По умолчанию для сервера задан локальный адрес 0.0.0.0 , также записанный * , что означает, что на этом порту будет только один прослушивающий сокет, и он будет принимать весь входящий трафик на этом порту.

Как вы обнаружили, он также уникален для каждого протокола.

Например, DNS-сервер BIND использует TCP и UDP:

# netstat -nlp | grep named
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      567/named
tcp        0      0 192.168.x.y:53          0.0.0.0:*               LISTEN      567/named
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN      567/named
udp        0      0 127.0.0.1:53            0.0.0.0:*                           567/named
udp        0      0 192.168.x.y:53          0.0.0.0:*                           567/named

Каждое соединение также уникально для каждого семейства протоколов, то есть IPv4 и IPv6 могут различаться.

Это зависит от того, запрашивал ли программист сокет только для IPv4, сокет только для IPv6 или комбинированный сокет IPv4/IPv6.

В Linux сокет IPv6 также принимает трафик IPv4, если только программист не скажет, что нет, и поэтому он появляется только один раз в выводе netstat .

$ port=55555
$ nc -6 -l $port || echo "Error listening on port $port" &
$ netstat -tnl | grep $port
tcp6       0      0 :::55555                :::*                    LISTEN     
$ nc -z 127.0.0.1 $port && echo "Port $port is accepting IPv4 connections"
Port 55555 is accepting IPv4 connections

Но исходный код memcached показывает, что он явно запрашивает сокет только для IPv6, поэтому IPv4 и IPv6 появляются отдельно в вашем примере.

error = setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &flags, sizeof(flags));

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .