雙網卡服務器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).
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章