网络编程中有时明明用eth0的地址来bind一个udp套接口, 可是发出去的包却是从eht1走的, 在网上找到这么一段话解释该问题:
          在多 IP/网卡主机上,UDP 包/协议会自动根据路由最优来选择从哪个网卡发数据包出去,即使你在此之前把该 SOCKET 绑定到了另一个网卡上。这样一来,如果你执行了绑定,则在 UDP 包中所代表的源 IP 字段可能不是你的数据包真正发出的地址。
比如:你有两个网卡分别为:A—192.168.1.100; B-192.168.2.100; mask-255.255.255.0 
此时你如果将一 UDP 套接字 S 绑定到了 A 上,但是要发的目的地址为 192.168.2.110,这时包实际是从网卡 B 上发出去的(根据路由最优原则),但在包头的结构里面,由于 BIND 的缘故,可能指向的源地址为 A。这样源 IP 地址就产生了与实际不相符的错误。
  要解决这种问题, 可以把套接字绑定到一个指定的网络设备, "eth0", "ppp0"等.
 

三个示例:

 
1. example(TCP, UDP, RAW):
 

int sock;
struct ifreq ifr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
memset(&ifr, 0x00, sizeof(ifr));
strncpy(ifr.ifr_name, "eth0", IFNAMSIZE);
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr));

2. example(PACKET):
 

int sock;
struct sockaddr_ll sl;
struct ifreq ifr;
sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IPV6));
memset(&sl, 0x00, sizeof(sl));
memset(&ifr, 0x00, sizeof(ifr));
sl.sll_family = AF_PACKET;
sl.sll_protocol = htons(ETH_P_IPV6);
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
ioctl(fd, SIOCGIFINDEX, &ifr);
sl.sll_ifindex = ifr.ifr_ifindex;
bind(fd, (struct sockaddr *)&sl, sizeof(sl));

3. example(PACKET):
 

int sock;
struct sockaddr addr;
sock = socket(PF_PACKET, SOCK_PACKET, ETH_P_IP);
memset(&addr, 0x00, sizeof(addr));
addr.sa_family = PF_PACKET;
strncpy(addr.sa_data, "eth0", sizeof(addr.sa_data));
bind(sock, &addr, sizeof(addr));

针对SO_BINDTODEVICE套接口选项,man(7)手册有如下说明:
SO_BINDTODEVICE
Bind  this  socket  to  a particular device like “eth0”, as specified in the passed interface name.  If the name is an empty string or the option length is zero, the socket device binding  is  removed.   The  passed option  is a variable-length null-terminated interface name string with the maximum size of IFNAMSIZ.  If a socket is bound to an interface, only packets received from that particular interface are processed by  the socket.  Note  that  this  only works for some socket types, particularly AF_INET sockets.  It is not supported for packet sockets (use normal bind(8) there).

参考信息:
 

绑定socket描述符到一个网络设备的更多相关文章

  1. linux一切皆文件之tcp socket描述符(三)

    一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列) 2.操作这些不同的类型就像操作文件一样,比如增删改查等 二.环境准备 ...

  2. linux一切皆文件之Unix domain socket描述符(二)

    一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列) 2.操作这些不同的类型就像操作文件一样,比如增删改查等 3.主要用于 ...

  3. 【读书笔记】socket描述符选项[SOL_SOCKET]

    #include <sys/socket.h>    int setsockopt( int socket, int level, int option_name,             ...

  4. vue组件双向绑定.sync修饰符的一个坑

    我们知道组件是单项的,但是有时候需要双向,这时候我们可以使用.sync修饰符,但今天遇到一个坑,一直不成功,花了半小时试出来的.... 在编程的时候我们很习惯冒号后面跟着空格.而.sync双向绑定需要 ...

  5. linux内核中的文件描述符(二)--socket和文件描述符

    http://blog.csdn.net/ce123_zhouwei/article/details/8459730 Linux内核中的文件描述符(二)--socket和文件描述符 Kernel ve ...

  6. python描述符理解

    Python中的描述符是一个相对底层的概念 descriptor Any object which defines the methods get(), set(), or delete(). Whe ...

  7. 【转载】Python 描述符简介

    来源:Alex Starostin 链接:www.ibm.com/developerworks/cn/opensource/os-pythondescriptors/ 关于Python@修饰符的文章可 ...

  8. linux专题一之文件描述符、重定向、管道符、tee命令

    本节讨论一下几个问题: 1. 文件描述符. 2. 重定向. 3. 管道符 4. tee的用法. 1. 文件描述符. 在linux系统中一切皆文件.文件夹和设备都是文件.如何用来区别不同的文件呢?这里的 ...

  9. linux文件描述符--转载

    转自:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录 ...

随机推荐

  1. selenium用css、xpath表达式进行元素定位

    绝对路径选择 从根节点开始的,到某个节点,每层都依次写下来,每层之间用 / 分隔的表达式,就是某元素的 绝对路径 Xpath : /html/body/div CSS : html>body&g ...

  2. 为什么在匿名内部类中引用外部对象要加final修饰符

    当所在的方法的形参需要被内部类里面使用时,该形参必须为final. 为什么必须要为final呢? 首先我们知道在内部类编译成功后,它会产生一个class文件,该class文件与外部类并不是同一clas ...

  3. PHP设计模式之中介者模式

    上回说道,我们在外打工的经常会和一类人有很深的接触,那就是房产中介.大学毕业后马上就能在喜欢的城市买到房子的X二代不在我们的考虑范围内哈.既然需要长期的租房,那么因为工作或者生活的变动,不可避免的一两 ...

  4. TP5.0版本mysql查询语句 闭包

    Db::name('tiwen') ->where('user_id', $user_id) ->where(function ($query) { $query->where(fu ...

  5. win10 移动端 android 测试环境搭建

    一.移动端自动化测试的基础环境配置1:安装Java环境 关于安装Java环境以及相关环境变量的配置在我之前的博文分享中已有详细介绍,有需要的可以直接查找翻阅,这里就不再一一介绍. 二.移动端自动化测试 ...

  6. oracle 基础SQL语句 版本5.7.29

    一.表与用户介绍 oracle安装完成后默认会有很多用户,大致分为2类用户:一类是必需的帐户,一类是存储各种应用的帐户,默认密码如下: oracle自带的也会有很多默认表存在: 二.创建用户.创建表空 ...

  7. Python : TypeError: 'int' object is not iterable

    用循环依次对list中的每个名字打印出 Hello, xxx! -------------------------------------------------------- L = ['Bart' ...

  8. gcc、g++、gdb安装

    Windows安装 有闲工夫在Windows上安装g++/gcc/gdb,还不如装个虚拟机安装Linux,在Linux上安装 但是我还是要讲的 首先,需要安装MinGW,MinGW,是Minimali ...

  9. 高中最后一刻&大学第一课&为人师的责任

    文章不是技术文,只是分享一些感想,作为一只程序猿,不说好好敲代码,跑出来思考人生,不是合格的程序猿,罪过罪过,自我反思3秒钟,我们继续,毕竟程序猿的人生不只是Coding,也希望自己这点感想被更多刚入 ...

  10. SpringBoot-邮件任务

    邮件发送,在我们的日常开发中,也非常的多,Springboot也帮我们做了支持 邮件发送需要引入spring-boot-start-mail SpringBoot 自动配置MailSenderAuto ...