哪些协议值与socket()中的域和类型组合兼容?

时间:2017-03-02 20:56:23

标签: sockets tcp network-programming c++14 berkeley-sockets

我正在玩伯克利插座,然后我这样做了:

#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()调用中使用第3个参数,如果我们有 已经指定SOCK_STREAM(TCP)作为第二个参数中的协议,即这个protocol(第三个参数)存在的原因是什么?

  2. 如果protocol(第三个参数)是必要的,那么它可以采用的是什么值 包含domain(第一个参数)和type的所有可能组合(第二个 参数)?

  3. 如果有人可以通过示例解释这一点,那将非常有帮助,否则它也会没问题。 感谢

1 个答案:

答案 0 :(得分:1)

  1. 根据我的经验,协议字段通常仅在使用SOCK_RAW而不是SOCK_DGRAM或SOCK_STREAM时使用。
  2. protocol可以接受的值取决于前两个参数的值。列出的here列出了可用的域和类型。同一页面上有关于protocol字段的以下内容:
  3.    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.
    

    这是列出可用协议及其相关值的link to a page。 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);
    

    另请查看this answer其他问题。它讨论的是正常的ICMPv4插座,但它仍然有用,有些部分可能适用。