Linux: sockaddr_storage, как его инициализировать? - PullRequest
0 голосов
/ 05 июня 2018

У меня есть программа на основе TCP, которая поддерживает IPv4 и IPv6.Поэтому в коде я использовал «sockaddr_storage».

На стороне client мне нужно привязать TCP-порт клиента к определенному, поэтому янужно привязать сокет к этому адресу.

struct sockaddr_storage local_addrs; //for local address

if (sc->domain == AF_INET) {
    (*(struct sockaddr_in*)&local_addrs).sin_family = AF_INET;
    (*(struct sockaddr_in*)&local_addrs).sin_addr.s_addr = inet_addr(INADDR_ANY);
    (*(struct sockaddr_in*)&local_addrs).sin_port = htons(tcp_port);
}
else{
    (*(struct sockaddr_in6*)&local_addrs).sin6_family = AF_INET6; 
    (*(struct sockaddr_in6*)&local_addrs).sin_addr.s_addr = inet_addr(IN6ADDR_ANY_INIT);
    (*(struct sockaddr_in6*)&local_addrs).sin6_port = htons(tcp_port);
}

local_addr_size = sizeof(local_addrs);
if (( ret = bind(sockfd, (struct sockaddr *)&local_addrs, local_addr_size)) < 0 ) {
    ....//error
}

Как мне инициализировать struct sockaddr_storage local_addrs?Нужно ли malloc памяти для этой структуры?

Кстати, нижняя строка пока не работает.Все еще пытаюсь выяснить, как связать клиентский соксет с любыми возможными адресами IPv6.

(*(struct sockaddr_in6*)&local_addrs).sin_addr.s_addr = inet_addr(IN6ADDR_ANY_INIT);

1 Ответ

0 голосов
/ 06 июня 2018

Код, который вы показали, в основном правильный путь, в котором вам нужно набрать sockaddr_storage к конкретному типу sockaddr_..., который вы хотите заполнить.

Однако вв случае sockaddr_in6 часть IN6ADDR_ANY_INIT неверна.Используйте это вместо:

(*(struct sockaddr_in6*)&local_addrs).sin6_addr = in6addr_any;

IN6ADDR_ANY_INIT - это макрос, который может использоваться только в статических объявлениях во время компиляции, например:

struct sockaddr_in6 in6 = {AF_INET6, port, 0, IN6ADDR_ANY_INIT, 0};

struct in6_addr addr = IN6ADDR_ANY_INIT;

IN6ADDR_ANY_INIT нельзя использовать в назначениях во время выполнения, например:

struct sockaddr_in6 in6;
in6.sin6_addr = IN6ADDR_ANY_INIT; // ERROR

struct in6_addr addr;
addr = IN6ADDR_ANY_INIT; // ERROR

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

И нет, вам не нужно malloc структуру sockaddr_storage.

При этом я бы предложил использовать некоторые локальные переменные, чтобы сделать код прощечитать:

if (sc->domain == AF_INET) {
    struct sockaddr_in *in4 = (struct sockaddr_in*) &local_addrs;
    in4->sin_family = AF_INET;
    in4->sin_addr.s_addr = INADDR_ANY; // <-- inet_addr() is not needed for INADDR_ANY
    in4->sin_port = htons(tcp_port);
}
else {
    struct sockaddr_in6 *in6 = (struct sockaddr_in6*) &local_addrs;
    in6->sin6_family = AF_INET6;
    in6->sin6_addr = in6addr_any;
    in6->sin6_port = htons(tcp_port);
    /* note: sockaddr_in6 also has sin6_flowinfo and sin6_scope_id
       fields that you may have to fill, too...
    in6->sin6_flowinfo = ...;
    in6->sin6_scope_id = ...;
    */
}

Или используйте вместо него union:

union sockaddr_types {
    struct sockaddr_storage storage;
    struct sockaddr addr; 
    struct sockaddr_in in4;
    struct sockaddr_in6 in6;
};

union sockaddr_types local_addrs;

if (sc->domain == AF_INET) {
    local_addrs.in4.sin_family = AF_INET;
    local_addrs.in4.sin_addr.s_addr = INADDR_ANY;
    local_addrs.in4.sin_port = htons(tcp_port);
}
else {
    local_addrs.in6.sin6_family = AF_INET6;
    local_addrs.in6.sin6_addr = in6addr_any;
    local_addrs.in6.sin6_port = htons(tcp_port);
    /*
    local_addrs.in6.sin6_flowinfo = ...;
    local_addrs.in6.sin6_scope_id = ...;
    */
}

if ((ret = bind(sockfd, &local_addrs.addr, sizeof(local_addrs))) < 0) {
    //error...
}

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

memset(&local_addrs, 0, sizeof(local_addrs));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...