Понимание INADDR_ANY для программирования сокетов

Я пытаюсь запрограммировать несколько сокетов и поэтому на стороне сервера использую htonl(INADDR_ANY), Насколько я понял, мне кажется, что эта функция генерирует случайный IP (я прав?). На самом деле, я хочу связать мою розетку с моим localhost, Но если я запущу это

printf("%d",htonl(INADDR_ANY));

Я получаю 0 в качестве возвращаемого значения. Может ли кто-нибудь привести какое-то объяснение?

7 ответов

Решение
  1. bind() из INADDR_ANY НЕ "генерирует случайный IP". Он связывает сокет со всеми доступными интерфейсами.

  2. Для сервера вы обычно хотите связать все интерфейсы, а не только "localhost".

  3. Если вы хотите привязать свой сокет только к localhost, синтаксис будет my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");затем позвоните bind(my_socket, (SOCKADDR *) &my_sockaddr, ...),

  4. Как это происходит, INADDR_ANY константа, которая равна "нулю":

    http://www.castaglia.org/proftpd/doc/devel-guide/src/include/inet.h.html

    # define INADDR_ANY ((unsigned long int) 0x00000000)
    ...
    # define INADDR_NONE    0xffffffff
    ...
    # define INPORT_ANY 0
    ...
    
  5. Если вы еще не знакомы с ним, я призываю вас ознакомиться с Руководством Beej по программированию сокетов:

    http://beej.us/guide/bgnet/

Так как люди все еще читают это, дополнительное примечание:

man (7) ip:

Когда процесс хочет получить новые входящие пакеты или соединения, он должен связать сокет с адресом локального интерфейса, используя bind (2).

В этом случае только один IP-сокет может быть связан с любой данной локальной парой (адрес, порт). Если в вызове bind указано INADDR_ANY, сокет будет привязан ко всем локальным интерфейсам.

Когда listen(2) вызывается для несвязанного сокета, сокет автоматически связывается со случайным свободным портом с локальным адресом, установленным в INADDR_ANY.

Когда connect(2) вызывается для несвязанного сокета, сокет автоматически связывается со случайным свободным портом или с используемым общим портом с локальным адресом, установленным в INADDR_ANY...

Существует несколько специальных адресов: INADDR_LOOPBACK (127.0.0.1) всегда ссылается на локальный хост через устройство обратной связи; INADDR_ANY (0.0.0.0) означает любой адрес для привязки...

Также:

bind () - привязывает имя к сокету:

Если в поле (sin_addr.s_addr) задано постоянное значение INADDR_ANY, как определено в netinet/in.h, вызывающая сторона запрашивает привязку сокета ко всем сетевым интерфейсам на хосте. Затем UDP-пакеты и TCP-соединения от всех интерфейсов (которые соответствуют связанному имени) направляются в приложение. Это становится важным, когда сервер предлагает услугу нескольким сетям. Если адрес не указан, сервер может принимать все UDP-пакеты и запросы TCP-соединения, сделанные для его порта, независимо от сетевого интерфейса, на который поступили запросы.

INADDR_ANY используется, когда вам не нужно привязывать сокет к определенному IP. Когда вы используете это значение в качестве адреса при звонке bind(), сокет принимает соединения со всеми IP-адресами машины.

Чтобы связать сокет с локальным хостом, перед вызовом функции связывания поле sin_addr.s_addr структуры sockaddr_in должно быть правильно установлено. Правильное значение может быть получено либо

my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1")

или

my_sockaddress.sin_addr.s_addr=htonl(INADDR_LOOPBACK);

INADDR_ANY дает команду прослушивающему сокету связываться со всеми доступными интерфейсами. Это то же самое, что пытаться связать inet_addr("0.0.0.0"), Для полноты я также упомяну, что для IPv6 также есть IN6ADDR_ANY_INIT, и это то же самое, что пытаться связать :: адрес для сокета IPv6.

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

Также обратите внимание, что при привязке сокета IPv6 к IN6ADDR_ANY_INIT Ваш сокет будет привязан ко всем интерфейсам IPv6 и должен иметь возможность принимать соединения от клиентов IPv4 (хотя адреса, сопоставленные с IPv6).

Когда у вас есть сервер, вы создаете сокет, а затем привязываете его к IP-адресу и порту, что дает сокету уникальный способ идентификации на основе уникального типа сокета, семейства адресов, IP-адреса и порта. Затем вы listen(), чтобы установить сокет в режим сервера, а затем вы выполняете accept(), который ожидает соединения, которое будет иметь входящие пакеты с целевыми параметрами, которые вызывают постановку пакетов в очередь на этом сокете.

Когда у вас есть клиент, вы создаете сокет, а затем подключаете () сокет к удаленному IP-адресу и порту, который также привяжет 0.0.0.0 и случайный неиспользуемый эфемерный порт к сокету, если он еще не был привязан. к IP-адресу и порту с помощью привязки (INADDR_ANY, 0). connect() возвращается при подключении и использует IP-адрес и порт в качестве исходного адреса в исходящих пакетах, где 0.0.0.0 всегда заменяется ОС на текущий внутренний IP-адрес, а затем вы используете sendall для отправки данных приложения.

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

Обратите внимание, что сокет может быть привязан к 0.0.0.0, но не к порту 0, потому что это подстановочный знак, который заставляет его назначать сокету случайный эфемерный порт, поэтому, когда вы используете привязку (INADDR_ANY, 0), он привязывается к 0.0.0.0 и случайный эфемерный порт.

INADDR_ANY - это константа, которая содержит 0 в значении. это будет использоваться только тогда, когда вы хотите подключиться со всех активных портов, которые вам не нужны для ip-add. поэтому, если вы хотите подключить какой-либо конкретный ip, вы должны упомянуть как my_sockaddress.sin_addr.s_addr = inet_addr("192.168.78.2")

      #include <arpa/inet.h>                                                                     
.                                                                                   
.                                                                                        
tcpsock.sin_addr.s_addr = inet_addr("192.168.1.2")

работал на меня

Другие вопросы по тегам