我正在玩伯克利插座,然后我这样做了:
#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
,程序运行正常。
所以我的问题是:
为什么需要在socket()调用中使用第3个参数,如果我们有
已经指定SOCK_STREAM
(TCP)作为第二个参数中的协议,即这个protocol
(第三个参数)存在的原因是什么?
如果protocol
(第三个参数)是必要的,那么它可以采用的是什么值
包含domain
(第一个参数)和type
的所有可能组合(第二个
参数)?
如果有人可以通过示例解释这一点,那将非常有帮助,否则它也会没问题。 感谢
答案 0 :(得分:1)
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插座,但它仍然有用,有些部分可能适用。