【发布时间】:2012-09-11 13:55:48
【问题描述】:
是否可以将 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权限运行,否则它会抛出一个错误,说“不允许操作”。
【问题讨论】:
-
@E_net4:很多原因,取决于你想要做的流量类型。只听特定的IP。订阅该 IP 上的多播流量。选择多个 IP 之一作为连接的原始 IP。
-
您能否提供一个完整的示例,我们可以自己编译和查看?我不清楚 ifr 和套接字中的其他值到底是什么。我正在使用该 setsockopt 很好地绑定到接口,因此这些字段中的任何一个都可能是错误的。具体来说,端口可能很有趣,功能明智。
-
@E_net4 该应用程序将与一个网络上的内部组件以及另一个网络上的客户端进行通信。当客户端连接时,套接字最终可能会绑定到错误的接口。
-
@PlasmaHH 该代码是我应用程序中库的套接字包装器的一部分。接口名称是传入的,所以它就像“eth0”或“eth2”。
-
某些平台可能支持 SO_BINDTODEVICE,但不一定是可移植的。 setsockopt 调用是否返回成功?如果此 setsockopt 不起作用,您可以使用原始套接字,但这也需要提升权限。