Chinaunix首页 | 论坛 | 博客
  • 博客访问: 23899
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 55
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-23 16:08
个人简介

像蜗牛一样缓缓的爬向金字塔的顶端。

文章分类
文章存档

2015年(1)

2014年(8)

我的朋友

分类: C/C++

2014-11-07 10:37:46

事情的起因是我准备用两个CDMA modem来拓展点对点连接的带宽,并且希望藉此实现两个modem之间的负载均衡。但是不幸的是,联通公司的接入设备不支持Multilink-PPP。于是,没有办法,我只好自己来实现负载均衡。实现负载均衡的办法有几种,网络上给出的一种办法是采用iproute2来完成包级别的负载均衡,这是在内核一级实现的。但是我并不想把一切都交给内核去完成,我希望能够自己控制每一个modem上的流量。那么,我应该怎么办呢?


SO_BINDTODEVICE

在socket(7)中对该套接口选项的说明如下:当套接口被绑定到指定的网络设备接口之后,只有来自该设备的数据包才会被套接口处理。那么,如果是套接口向外发送数据包呢?是否也只会从该网络接口发出呢?

在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)绑定到指定的网络接口上的



http://blog.163.com/liukang_0404@126/blog/static/556825812012313114324623/


阅读(8547) | 评论(0) | 转发(0) |
0

上一篇:起航

下一篇:linux下串口gps应用

给主人留下些什么吧!~~