像蜗牛一样缓缓的爬向金字塔的顶端。
分类: C/C++
2014-11-07 10:37:46
在Linux下,对网络设备的引用都是通过struct ifreq来完成的。在netdevice(7)中对该结构体的说明如下:
struct ifreq {
char ifr_name[IFNAMSIZ];/* Interface name */
union {
struct sockaddrifr_addr;
struct sockaddrifr_dstaddr;
struct sockaddrifr_broadaddr;
struct sockaddrifr_netmask;
struct sockaddrifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmapifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char * ifr_data;
};
};
这里,我只需要ifr_name这个成员域就够了。代码修改成了下面这样:
struct ifreq if_ppp0;
struct ifreq if_ppp1;
strncpy(if_ppp0.ifr_name, "ppp0", IFNAMSIZ);
strncpy(if_ppp1.ifr_name, "ppp1", IFNAMSIZ);
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)) < 0) {
/*error handling*/
}
if (setsockopt(sock2, SOL_SOCKET, SO_BINDTODEVICE,
(char *)&if_ppp1, sizeof(if_ppp1)) < 0) {
/*error handling*/
}
然后,在程序的主体部分,每次在sock1上发送一个数据包,同时也就会在sock2上发送一个数据包,并且程序中没有任何接收数据的动作。由于所有数据包的大小都是相等的。因此可以预计在两个网络接口上发送的数据量应该相差不大才对。测试结果有力地支持了这一猜想:在运行程序一段时间后,接口ppp0上发送的数据量为702KB,而ppp1接口上发送的数据量为895KB。虽然仍然相差了将近200KB,但是无论如何,比起原来的情况已经提高了不少。
针对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套接口(2 layer),上述结论是可信的,因为我阅读了dhcpd的源代码,发现对于PACKET套接口的确是通过bind(2)绑定到指定的网络接口上的