IPPROTO_IP与IPPROTO_TCP/IPPROTO_UDP的区别

30
我在查找关于第三个参数设置区别的文档时遇到些困难,我知道TCP和UDP之间的差异以及IP位于堆栈中的哪一层,但是无论我将UDP代码设置为“ IPPROTO_IP”还是“ IPPROTO_UDP”,它都能正常工作。

2个回答

33

Linux中socket()的文档分散在各种手册页中,包括指定您必须使用0IPPROTO_UDP来进行UDP通信以及使用0IPPROTO_TCP来进行TCP通信的ip(7)。当您使用0时,它恰好是IPPROTO_IP的值,用于SOCK_DGRAM的是UDP,用于SOCK_STREAM的是TCP。

我认为创建UDP或TCP IPv4套接字对象的简洁方法如下:

int sock_udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int sock_tcp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

之所以这样做,是因为明确比含蓄更好。在这种特定情况下,使用 0 或者更糟糕的 IPPROTO_IP 作为第三个参数并没有任何好处。

此外,想象一下使用可以同时进行流和数据报的协议,比如 sctp。通过始终指定 socktypeprotocol,您可以避免任何歧义。


0

来自Linux手册页中的socket(2),来自man-pages 5.08:

通常,在给定协议族中支持特定套接字类型的只有一个协议存在,此时可以将协议指定为0。但是,可能存在许多协议,此时必须以这种方式指定特定协议。

IPPROTO_IP只是IPPROTO_*系列中的常规占位符常量,在socket API中的值为0,自早期以来一直如此。

当然,为了前向兼容性,如果将来为协议族添加更多的套接字类型,这可能会破坏UDP/TCP的0或更改其行为,最好查找所需协议的特定协议值并使用它,而不是使用0IPPROTO_IP

请注意,IPPROTO_*头值在不同的上下文中具有多种用途:除了在套接字API和其实现代码内部中用作参数值以标识协议之外,它们还用作IP数据包本身中IP协议字段的值。这些IP协议值,或者在IANA术语中的协议号码,本身具有另一个目的,即在IPv6中标识不同的扩展头类型。这就是为什么0也是IPPROTO_HOPOPTS,它是IPv6跳跃选项扩展头的标识符。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接