Какие значения протокола совместимы с какими комбинациями домена и типа в socket()?

Я играл с розетками Беркли, а затем я сделал это:

#include <iostream>
#include <sys/socket.h>
#include <cstring>

int main()
{
    auto res = socket(AF_INET6, SOCK_STREAM, 58);
    if (res < 0) {
        std::cout << "  Error in creating socket: " << strerror(errno) << '\n';
    }
    return 0;
}

И вывод был: Error in creating socket: Protocol not supported, Я выбрал 58, так как хотел попробовать в качестве примера сокет ICMP IPv6 и использовать содержимое /etc/protocols Я получил это: ipv6-icmp 58 IPv6-ICMP # ICMP for IPv6, Потом я попробовал 0 на месте 58 в приведенном выше коде, и программа работает нормально. Итак, мои вопросы:

  1. зачем нужен этот третий параметр в вызове socket(), если
    уже указано SOCK_STREAM(TCP) в качестве протокола по 2-му параметру, т.е. какова причина существования этого protocol (3-й параметр)?

  2. Если protocol(3-й аргумент) необходимо тогда, что все значения могут принимать
    со всеми возможными комбинациями domain(1-й аргумент) и type(2-й аргумент)?

Было бы очень полезно, если бы кто-то мог объяснить это примерами, иначе тоже было бы хорошо. Спасибо

1 ответ

  1. По моему опыту, поле протокола обычно используется только тогда, когда вы используете SOCK_RAW вместо SOCK_DGRAM или SOCK_STREAM.
  2. значения, которые protocol можно принять в зависимости от значений первых двух аргументов. Доступные домены и типы перечислены здесь. На этой же странице сказано следующее о protocol поле:
   The protocol specifies a particular protocol to be used with the
   socket.  Normally only a single protocol exists to support a
   particular socket type within a given protocol family, in which case
   protocol can be specified as 0.  However, it is possible that many
   protocols may exist, in which case a particular protocol must be
   specified in this manner.  The protocol number to use is specific to
   the “communication domain” in which communication is to take place;
   see protocols(5).  See getprotoent(3) on how to map protocol name
   strings to protocol numbers.

Вот ссылка на страницу со списком доступных протоколов и связанных с ними значений. Значение протокола ICMP равно 1.

Для настройки ICMP-пакетов вы можете сделать следующее: sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

для настройки пакетов UDP вы бы использовали

sock = socket(AF_INET, SOCK_DGRAM, 0);

или же

sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);

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

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