Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 將 Socket 綁定到指定網路介面 (SO_BINDTODEVICE) 實作

編輯:Linux 教學

緣起:雙 CDMA Modem 負載平衡需求

欲以兩張 CDMA Modem 擴展點對點頻寬並實現負載平衡,但 ISP 設備不支援 Multilink-PPP,需自行實作。

嘗試與失敗

  1. 綁定本地 IP:以為綁定 IP 即可決定出口介面,實則核心依路由表決定,導致單一介面被高速快取反覆命中,另一介面閒置。
  2. 每發送前修改路由表:理論可行但過於繁瑣,未實測。
  3. SO_DONTROUTE:man page 說明模糊,實測無效。

關鍵發現:SO_BINDTODEVICE

在 man 7 socket 發現 SO_BINDTODEVICE:將 Socket 綁定至指定介面(如 eth0),收發封包皆限定該介面。但 man page 僅說明接收端行為,發送端需實測。

正確用法:需搭配 struct ifreq

Linux 參考網路介面皆透過 struct ifreq(定義於 netdevice(7)),僅需填寫 ifr_name。

程式碼範例

struct ifreq if_ppp0, 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);

setsockopt(sock1, SOL_SOCKET, SO_BINDTODEVICE, (char *)&if_ppp0, sizeof(if_ppp0));
setsockopt(sock2, SOL_SOCKET, SO_BINDTODEVICE, (char *)&if_ppp1, sizeof(if_ppp1));

實測結果

主程式輪流在 sock1、sock2 發送等大小封包。運行一段時間後:ppp0 發送 702 KB,ppp1 發送 805 KB,負載分配明顯改善(原情況一介面發送數百 KB,另一僅數十 Bytes)。

總結結論

  1. TCP、UDP、RAW Socket 可用 SO_BINDTODEVICE 綁定介面,收發皆限定該介面。
  2. PACKET Socket 不支援此選項,需用 bind(2) 搭配 struct sockaddr_ll(鏈路層位址,獨立於具體裝置)。
  3. SO_BINDTODEVICE 為 Linux 專有,跨平台程式不可依賴。
註:TCP/RAW Socket 未實測,PACKET Socket 結論參考 dhcpd 原始碼驗證。
Copyright © Windows教程網 All Rights Reserved