Розуміння INADDR_ANY для програмування сокетів


84

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

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

Я отримую 0 як повернене значення. Хтось міг би пояснити якесь пояснення?


9
" ... Я використовую htonl(INADDR_ANY). Документ каже, що ця функція генерує випадковий IP ... " Це неправильно. Які документи вам про це говорять?
alk

1
@alk, насправді я ввожу в оману: я читав PDF-файл, який, на мою думку, був офіційною документацією. Я редагую свій пост зараз
epsilones

Відповіді:


132
  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/

Оскільки люди все ще читають це, додаткова примітка:

людина (7) ip :

Коли процес хоче отримати нові вхідні пакети або з'єднання, він повинен прив'язати сокет до адреси локального інтерфейсу за допомогою bind (2) .

У цьому випадку лише один сокет IP може бути прив’язаний до будь-якої заданої локальної пари (адреса, порт). Коли в виклику прив'язки вказано 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, зроблені для його порту, незалежно від мережевого інтерфейсу, на який надійшли запити.


4
Це не означає "прив'язка до всіх інтерфейсів". Якби це було зроблено, вихід netstat був би іншим. Це означає "слухати на будь-якому інтерфейсі".
Маркіз Лорнський

6
Щоб процитувати вищевказане посилання: "Коли INADDR_ANY вказано у виклику прив'язки, сокет буде прив'язаний до всіх локальних інтерфейсів." З іншого посилання: Значення "INADDR_ANY" означає, що ми будемо прив'язуватись до будь-якої / усіх IP-адрес, які наразі має локальний комп'ютер . Але так - багато реалізацій будуть прив’язані до першого інтерфейсу, (не "всіх"). Але для одного ПК з одним мережевим адаптером різниця є академічною. За допомогою INADDR_ANY клієнт може підключатися до будь-якого / усіх IP-адрес (наприклад, як 192.168.1.2, так і 127.0.0.1).
paulsm4

5
Вибачте, якщо це дурне запитання, але чи означає інтерфейс бездротовий зв'язок, Ethernet тощо?
mrQWERTY

3
@ laike9m Ви повинні прив'язатись до 127.0.0.1, коли хочете мати можливість підключатися до розетки лише з локальної машини. Для цього існують випадки використання, коли послуга, яку пропонує сокет, призначена лише для використання в іншому процесі, який є локальним для машини.
dgnuff

2
@ paulsm4 У 3, чи не можете ви використовувати INADDR_LOOPBACK, а не inet_addr("127.0.0.1")?
John Strood

62

INADDR_ANYвикористовується, коли не потрібно прив’язувати сокет до певної IP-адреси. Коли ви використовуєте це значення як адресу під час виклику bind(), розетка приймає підключення до всіх IP-адрес машини.


8

Щоб прив'язати сокет до localhost , перед тим, як викликати функцію прив'язки , поле 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);

4

INADDR_ANYдоручає прослуховуванню сокета прив'язуватись до всіх доступних інтерфейсів. Це те саме, що намагатися прив’язати inet_addr("0.0.0.0"). Для повноти я також згадаю, що існує також IN6ADDR_ANY_INIT для IPv6, і це те саме, що намагатися прив’язати ::адресу до сокету IPv6.

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

Крім того, зауважте, що коли ви прив’язуєте сокет IPv6 до IN6ADDR_ANY_INITвашого сокету, він прив’язуватиметься до всіх інтерфейсів IPv6, і він також повинен приймати підключення від клієнтів IPv4 (хоча адреси, зіставлені з IPv6).


2

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.