【发布时间】:2011-05-16 21:22:03
【问题描述】:
如果一台计算机有多个网卡,它们都连接到不同的网络并正常工作,当我们打开一个套接字时,操作系统如何确定该套接字使用哪个网卡?套接字 API 是否允许我们明确指定要使用的 NIC?
【问题讨论】:
标签: sockets networking
如果一台计算机有多个网卡,它们都连接到不同的网络并正常工作,当我们打开一个套接字时,操作系统如何确定该套接字使用哪个网卡?套接字 API 是否允许我们明确指定要使用的 NIC?
【问题讨论】:
标签: sockets networking
我是从 Linux 的角度来写这篇文章的,但我想它适用于所有地方。
在绑定套接字时做出决定。当bind 被调用时,你指定的地址决定了套接字将监听的接口。 (甚至所有接口。)
即使您不使用bind,它也会在您connect 时隐式发生。在路由表中查找目的地,该表必须包含到目的地网络的路由。路由还包含要使用的接口,甚至可以选择指定源地址。如果不指定源地址,则取接口的主地址。
您实际上可以将bind 与connect 一起使用,以强制您的传出 连接使用特定地址和端口。套接字必须始终具有这两位信息,因此即使您没有,也会使用主地址并选择随机端口。
【讨论】:
bind 如何确定这一点?如果您在同一个子网上有多个接口怎么办?
bind() 到 IP 时,您将绑定到 IP 所属的特定接口。不能有多个具有相同 IP 的接口。
bind() 将失败。
我什至与此问题无关时,我不知道为什么我包含在编辑建议中。我之前也收到过类似的编辑建议..可能是一些错误/问题。
(如果您愿意投票,@Shtééf 的回答比我的更值得。)
这取决于你是连接还是绑定。
如果你绑定,你可以绑定到与机器的一个接口对应的特定IP地址,或者你可以绑定到0.0.0.0,在这种情况下,套接字将监听所有接口。
如果您连接一个未绑定的套接字,那么机器的路由表连同目标 IP 地址将确定连接请求在哪个接口发出。
可以绑定一个套接字然后连接它。在这种情况下,套接字在建立连接时将根据绑定调用保持绑定。 (感谢@RemyLebeau 指出这一点。)
【讨论】:
connect() 之前调用 bind()为出站连接使用特定的 IP/适配器。如果没有事先调用bind(),connect() 会决定使用哪一个。
我不确定哪种方法最好,但是 Shtéf 提出的 bind()-before-connect() 方法有另一种理论。将 setsockopt() 与 SO_BINDTODEVICE 一起使用。见:http://codingrelic.geekhold.com/2009/10/code-snippet-sobindtodevice.html
【讨论】:
作为替代方法,您可以根据其名称搜索适当的 nic:
//Find the ip address based on the ethernet adapter name. On my machine the ethernet adapter is "Ethernet"
System.Net.NetworkInformation.NetworkInterface[] nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
System.Net.NetworkInformation.NetworkInterface ethernet = nics.Where(n => n.Name.Equals("Ethernet")).Single();
UnicastIPAddressInformation uniCastIPAddressInformation = ethernet.GetIPProperties().UnicastAddresses.Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).Single();
IPEndPoint localEndPoint = new IPEndPoint(uniCastIPAddressInformation.Address, 9000);
//Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bind and start listening
listener.Bind(localEndPoint);
listener.Listen(10);
【讨论】: