sock1 = socket(AF_INET, SOCK_DGRAM, 0);
sock2 = socket(AF_INET, SOCK_DGRAM, 0);
if (setsockopt(sock1, SOL_SOCKET, SO_BINDTODEVICE,
(char *)&if_ppp0, sizeof(if_ppp0))
/*error handling*/
}
if (setsockopt(sock2, SOL_SOCKET, SO_BINDTODEVICE,
(char *)&if_ppp1, sizeof(if_ppp1))
/*error handling*/
}
然后,在程式的主体部分,每次在sock1上发送一个数据包,同时也就会在sock2上发送一个数据包,并且程式中没有所有接收数据的动作。由于所有数据包的大小都是相等的。因此能预计在两个网络接口上发送的数据量应该相差不大才对。测试结果有力地支持了这一猜想:在运行程式一段时间后,接口ppp0上发送的数据量为702KB,而ppp1接口上发送的数据量为895KB。虽然仍然相差了将近200KB,不过无论怎么,比起原来的情况已提高了不少。至于为什么会有这样200KB的差距,作者也正在找原因。
3. 更多结论
针对SO_BINDTODEVICE套接口选项,作者在全方面阅读man手册之后,得出的结论如下:
(1)对于TCP套接口、UDP套接口、RAW套接口,能通过SO_BINDTODEVICE套接口选项将套接口绑定到指定的网络接口上。绑定之后,套接口的所有数据包收发都只经过指定的网络接口;
(2)对于PACKET类型的套接口,不能通过SO_BINDTODEVICE绑定到指定的网络接口上,而要通过bind(2)来和特定的网络接口绑定,所用的套接口地址结构为struct sockaddr_ll,此套接口地址结构是链路层的地址结构,独立于具体的网络设备。比如,该地址结构既能用于表示PPP设备,也能用于表示ethernet设备。
(3)SO_BINDTODEVICE套接口选项只适用于Linux系统。如果要编写运行在多操作系统平台上的程式,不能依赖SO_BINDTODEVICE来完成套接口和具体设备的绑定。
不过,作者并没有对TCP套接口和RAW套接口进行测试。对于PACKET套接口,上述结论是可信的,因为我阅读了dhcpd的原始码,发现对于PACKET套接口的确是通过bind(2)绑定到指定的网络接口上的。