网络编程中有时明明用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. ESP8266- 使用AT指令获取网络时间

    前言:很早就考虑过用 ESP8266 获取网络时间,以前都是用 ESP8266 刷机智云的 Gagent 固件,但无奈现在手头的 ESP-01 的 Flash 只有 1M,实在无法胜任.经过在网络上的 ...

  2. HTML基本概念及基本标签

    HTML基本概念及基本语法 1.HTML的基本概念 1.1  B/S.C/S基本概念 B/S(Browser/Server):指的是浏览器端与服务器端工作模式,优点相对节省本地存储空间,不足是需要占用 ...

  3. CentOS Linux 简单安装 clickhouse

    本文只是仅仅的介绍安装 至于更多介绍请自信百度 1.本人 linux版本 [root@localhost /]# cat /etc/redhat-releaseCentOS Linux release ...

  4. express 路由匹配和数据获取

    express配置路由只需要通过app.method(url,func)来配置,其中url配置和其中的参数获取方法不同 直接写全路径 路由中允许存在. get请求传入的参数 router.get(&q ...

  5. Shell系列(38)- 数组操作→取值、遍历、替换、删除

    引言 在Linux平台上工作,我们经常需要使用shell来编写一些有用.有意义的脚本程序.有时,会经常使用shell数组.那么,shell中的数组是怎么表现的呢,又是怎么定义的呢?接下来逐一的进行讲解 ...

  6. php-抽象工厂

    目标:创建有依赖关系的实例;(套餐) <?php //抽象类 食物 interface IAllayFood { function Allay(); } interface IDrinkFood ...

  7. redis小结 1-2

    1.Redis 发布订阅 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis 客户端可以订阅任意数量的频道. 下图展示了频道 c ...

  8. MySQL8.0.20下载与安装详细图文教程,mysql安装教程

    MySQL下载与安装(8.0.20版)教程 mysql安装包+mysql学习视频+mysql面试指南视频教程 下载地址: 链接:https://pan.baidu.com/s/1FmLFhGlajBQ ...

  9. 编译原理: FIRST(x) FOLLOW(x) SELECT(x)的计算

    目录 First计算 Follow计算 Select计算 已知文法G[S]: S→MH|a H→LSo|ε K→dML|ε L→eHf M→K|bLM 判断G是否是LL(1)文法. First计算 F ...

  10. docker之swarm容器部署及运维

    1.概念 Docker Swarm 是 Docker 的集群管理工具.它将 Docker 主机池转变为单个虚拟 Docker 主机. Docker Swarm 提供了标准的 Docker API,所有 ...