• 绑定socket描述符到一个网络设备


         
     网络编程中有时明明用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).



    参考信息:
     
  • 相关阅读:
    Struts2第七篇【介绍拦截器、自定义拦截器、执行流程、应用】
    Struts2第六篇【文件上传和下载】
    过滤器和监听器的知识点大纲
    Struts2第五篇【类型转换器、全局、局部类型转换器】
    JSP知识点大纲图
    Servlet知识点大纲
    Struts2第四篇【请求数据自动封装、Action得到域对象】
    第八周项目3-分数类中的运算符重载
    第八周项目2-Time类中的运算符重载
    第八周项目1-实现复数类中的运算符重载
  • 原文地址:https://www.cnblogs.com/qigaohua/p/7461717.html
Copyright © 2020-2023  润新知