【问题标题】:Which protocol values are compatible with which combinations of domain and type in socket()?哪些协议值与 socket() 中的域和类型的哪些组合兼容?
【发布时间】:2017-07-22 18:58:21
【问题描述】:

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

#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) 作为协议,即这个protocol(第三个参数)存在的原因是什么?

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

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

【问题讨论】:

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


    【解决方案1】:
    1. 根据我的经验,协议字段通常仅在您使用 SOCK_RAW 而不是 SOCK_DGRAM 或 SOCK_STREAM 时使用。
    2. protocol 可以接受的值取决于前两个参数的值。可用的域和类型在here 中列出。同一页面对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.
    

    这是一个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 套接字,但它仍然应该有帮助,并且某些部分可能适用。

    【讨论】:

    • 好吧,我试过这个:auto res = socket(AF_INET6, SOCK_STREAM, 6);,它像魅力一样工作,然后我尝试了这个:auto res = socket(AF_INET6, SOCK_STREAM, 132);,它也像魅力一样工作,对于 0 它也有效,但除了这些3个值它给出错误`创建套接字时出错:不支持协议`。
    • 所以必须有一些标准/规则来指定什么时候可以使用哪些协议值,什么时候不可以使用?
    • @tkhurana96,根据我上面链接到的带有协议值的文档,6=TCP 和 132=SCTP。使用原始套接字尝试 ICMPv6 58。
    • @tkhurana96,这违背了我的理解。但我相信你的问题的答案比其他任何事情都更具历史意义。过去人们认为每个地址族都会支持许多不同的类型,每种类型都有自己的一组协议……但随着时间的推移,这最终并没有发生。多年来,套接字包装器已经出现以掩盖它,这样开发人员就不必处理它了。
    • 来自 Michael Kerrisk 的 Linux 编程接口:最初,人们认为单个协议族可能支持多个地址族。在实践中,还没有定义支持多个地址族的协议族,并且所有现有的实现都将 PF_ 常量定义为与相应的 AF_ 常量同义。 (SUSv3 指定了 AF_ 常量,但没有指定 PF_ 常量。)在本书中,我们总是使用 AF_ 常量。有关这些常数历史的更多信息,请参见 [Stevens et al., 2004] 的第 4.2 节。
    猜你喜欢
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 2023-03-30
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 2013-10-27
    相关资源
    最近更新 更多