Sockets 套接字如何知道要使用哪个网络接口控制器?

Sockets 套接字如何知道要使用哪个网络接口控制器?,sockets,networking,Sockets,Networking,如果一台计算机有多个网卡,所有网卡都连接到不同的网络并正常工作,那么当我们打开一个套接字时,操作系统如何确定该套接字使用哪个NIC?套接字API是否允许我们明确指定要使用的NIC 我不知道为什么我被包括在编辑建议中,而我甚至与这个问题无关。我以前也收到过类似的编辑建议。可能是一些错误/问题。 (如果你想投票,@Shtèf的回答比我更值得。) 这取决于您是连接还是绑定 如果绑定,则可以绑定到与计算机接口之一对应的特定IP地址,也可以绑定到0.0.0.0,在这种情况下,套接字将侦听所有接口 如果连接

如果一台计算机有多个网卡,所有网卡都连接到不同的网络并正常工作,那么当我们打开一个套接字时,操作系统如何确定该套接字使用哪个NIC?套接字API是否允许我们明确指定要使用的NIC

我不知道为什么我被包括在编辑建议中,而我甚至与这个问题无关。我以前也收到过类似的编辑建议。可能是一些错误/问题。

(如果你想投票,@Shtèf的回答比我更值得。)

这取决于您是连接还是绑定

如果绑定,则可以绑定到与计算机接口之一对应的特定IP地址,也可以绑定到0.0.0.0,在这种情况下,套接字将侦听所有接口

如果连接未绑定的套接字,则机器的路由表将与目标IP地址一起确定连接请求发出的接口


可以绑定一个套接字,然后连接它。在这种情况下,套接字在进行连接时将按照bind调用保持绑定状态。(感谢@RemyLebeau指出这一点。)

我是从Linux的角度写这篇文章的,但我想它适用于所有地方

这个决定是在绑定套接字时做出的。调用
bind
时,指定的地址决定套接字将侦听的接口。(甚至是所有接口。)

即使您不使用
bind
,它也会在您连接
时隐式发生。在路由表中查找目的地,该表必须包含到目的地网络的路由。路由还包含要使用的接口,甚至可以选择指定源地址。如果未指定源地址,则采用接口的主地址


实际上,您可以将
bind
connect
一起使用,以强制传出连接使用特定的地址和端口。套接字必须始终具有这两位信息,因此即使您没有,也会使用主地址并选择一个随机端口。

我不确定哪种方法是最好的,但对于Shtêéf提出的bind()-before-connect()方法,还有另一种理论。将setsockopt()与SO_BINDTODEVICE一起使用。请参阅:

您也可以根据相应nic的名称搜索该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);

除非在调用connect()之前调用bind()。@RemyLebeau实际上,这不一定是真的。在一篇关于“强端和弱端系统模型”的TCP RFC中有一个长期的讨论,结论是TCP只需要“弱端”模型。您所说的仅适用于“强端”模型。我不知道“弱端”和“强端”指的是什么,但我所知道的每个支持套接字的平台都允许在客户端需要使用特定的IP/适配器进行出站连接时,在
connect()
之前调用
bind()
。如果事先没有调用
bind()
,则由
connect()
决定使用哪一个。@RemyLebeau我不清楚。不一定正确的部分是,如果绑定到特定接口,连接请求将在该接口上发出。弱端系统模型允许情况并非如此。如果您不知道什么是强端系统模型和弱端系统模型,您可以随时查找它们。在RFCs中。如果在连接之前绑定到接口,则连接的本地地址将被绑定,连接请求必须使用该接口,否则将违反绑定。“调用绑定时,指定的地址将确定套接字将侦听的接口。”绑定如何确定这一点?如果在同一子网上有多个接口怎么办?如果我将套接字绑定到与任何接口都不匹配的ip地址怎么办?那么内核是否完成了NAT呢?