2

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

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

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

如果有人可以用示例解释这一点,那将非常有帮助,否则也可以。谢谢

4

1 回答 1

2
  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);

另请查看this answer to another question。它谈论的是普通的 ICMPv4 套接字,但它仍然应该有帮助,并且某些部分可能适用。

于 2017-03-02T20:58:28.800 回答