2016-08-12 29 views
0

要创建packet socket,以下socket()函数调用被使用(插座类型和协议可以是不同的):为什么在创建包套接字时使用htons()指定协议?

socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))

而创建stream socket,下面的调用用于:

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)

我的问题是为什么在创建packet socket时使用htons()指定协议,而不是在创建AF_INET or AF_INET6家族的套接字时指定协议?为什么不使用

socket(AF_INET, SOCK_XXX, htons(IPPROTO_XXX))

创建一个流或数据报套接字作为创建packet socket或反之亦然时使用。在socket()函数的两个调用中使用协议有什么不同,因为这两个调用都用于创建套接字,一个用于数据包套接字,另一个用于TCP层的套接字?

回答

0

首先,与传递给内核的大多数其他网络参数(IP地址,端口等)一样,参数以“在线”格式传递,因此底层软件无需操作他们在比较/复制/传输/等之前。 (为了比较,考虑到AF_PACKETSOCK_RAW是内核本身的参数 - 因此“原始格式”是合适的 - 而ETH_P_xxx值通常用于“与输入数据包比较”;恰巧ETH_P_ALL是一个特殊信号值说'捕获一切'。)

其次,协议的解释可能是不同的地址家庭。不同的地址系列可以选择以任何形式对该协议进行解释。恰恰是以太网和IP一直使用big-endian(并且很重要/无处不在,以至于big-endian被称为网络订单)。第三,AF_INET世界(即互联网协议)中的协议号码只占用一个字节,因此指定字节排序是没有意义的。

+0

Ethernet *和* IP *标头的在线格式*称为网络字节顺序(正如我在第二段中所解释的)。你可以把你想要的任何顺序“在电线上”。 –

+0

对于第1段,考虑到ETH_P_XXX值是“与传入数据包的比较”,那么为什么IPPROTO_XXX值没有转换为网络字节顺序。我明白第二段给出了上述问题的原因,即不同的协议族可以选择以对其有意义的形式来解释协议。那么这是否意味着它是功能开发人员的决定,因为他可以选择将函数内部的协议转换?对于第三段,协议号是作为int传递的,所以字节顺序确实有意义。如果我错了,请纠正。 – rht

+0

这样想:如果你在小端机器上比较两个16位值。有两种比较方法:(a)逐字节比较它们在存储器中出现的顺序,(b)将16位单元加载到寄存器中,然后进行比较。另一方面,对于单字节值,这两种方式都是相同的。 –