簡體   English   中英

如何在Linux中指定用於套接字的接口

[英]how to specify which interface to use for a socket in linux

是否可以將udp套接字綁定到特定接口,以便它通過該接口發送數據? 我有一個使用多個Udp套接字發送數據的應用程序,它正在具有多個接口的計算機上運行。 我知道可以通過使用以下代碼指定接口名稱來做到這一點:

int UdpSocket::open(const char *interface)
{
   send_fd_ = ::socket(AF_INET, SOCK_DGRAM, 0);
   if (send_fd_ < 0)
   {
      perror("socket");
      return -1;
   }

   int val = 1;
   int rc = ::setsockopt(send_fd_, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
   if (rc < 0)
   {
      perror("sesockopt");
      close();
      return -1;
   }

   unsigned char ttl = 16;
   rc = ::setsockopt(send_fd_, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
   if (rc < 0)
   {
      perror("sesockopt_ttl");
      close();
      return -1;
   }

   if (interface != NULL)
   {
      struct ifreq ifr;

      memset(&ifr, 0, sizeof(ifr));
      snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), interface);
      rc = ::setsockopt(send_fd_, SOL_SOCKET, SO_BINDTODEVICE, (void*)&ifr, sizeof(ifr));

      if (rc < 0)
      {
         perror("sesockopt");
         close();
         return -1;
      }
   }

   const int flags = ::fcntl(send_fd_, F_GETFL, 0);
   ::fcntl(send_fd_, F_SETFL, flags | O_NONBLOCK);

   return 0;
}

但這要求該應用程序具有root特權運行,否則它將引發錯誤,提示“不允許操作”。

最簡單,到目前為止也是最明智的方法是添加與多播目標匹配的route

~# route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

因為OS網絡堆棧會根據路由表為多播數據包選擇出站接口。 這也適用於偵聽-您只需綁定到組地址,內核就會為您選擇正確的接口。 您仍然必須照常加入該小組。

從聯機幫助頁:

SO_BINDTODEVICE

將此套接字綁定到特定的設備(如“ eth0”),如傳遞的接口名稱中所指定。 如果名稱為空字符串或選項長度為零,則刪除套接字設備綁定。 傳遞的選項是長度為NULLAM的可變長度接口名稱字符串,最大大小為IFNAMSIZ。 如果套接字綁定到接口,則套接字僅處理從該特定接口接收的數據包。 請注意,這僅適用於某些套接字類型,尤其是AF_INET套接字。 數據包套接字不支持此功能(在那里使用普通的bind(2))。

這意味着您必須自己(可能使用getifaddrs)從名稱中獲取接口,然后綁定到該地址。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM