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

发布于 2024-10-05 00:49:47 字数 98 浏览 0 评论 0原文

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

If a computer has multiple network cards, all of them connected to different networks and functioning properly, when we open a socket, how does the OS determine which NIC to use with this socket? Does the socket API allow us to explicitly specify the NIC that is to be used?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

魂归处 2024-10-12 00:49:47

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

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

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

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

I'm writing this from a Linux perspective, but I suppose it applies everywhere.

The decision is made when the socket is bound. When bind is called, the address you specify determines the interface the socket will listen on. (Or even all interfaces.)

Even if you don't use bind, it happens implicitly when you connect. The destination is looked up in the route table, which must contain a route to the destination network. The route also contains the interface to use and can optionally even specify the source address. If no source address is specified, the primary address of the interface is taken.

You can actually use bind together with connect, to force your outgoing connection to use a specific address and port. A socket must always have these two bits of information, so even when you don't, the primary address is used and a random port are chosen.

青巷忧颜 2024-10-12 00:49:47

我不知道为什么当我与这个问题无关时我会被包含在编辑建议中。我之前也收到过类似的编辑建议..可能是一些错误/问题。

(如果您倾向于投票,@Shtééf 的答案比我的更值得。)

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

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

如果连接未绑定的套接字,则计算机的路由表与目标 IP 地址一起将确定连接请求通过哪个接口发出。

可以绑定套接字然后连接它。在这种情况下,套接字在建立连接时将根据绑定调用保持绑定状态。 (感谢@RemyLebeau 指出了这一点。)

I dont know why im included in the edit suggestion when i was not even related to this question .I got similar edit suggestion before as well..might be some bug/issue.

(If you feel inclined to up-vote, @Shtééf's answer deserves it more than mine.)

That depends on whether you are connecting or binding.

If you bind, you can bind to a specific IP address corresponding to one of the machine's interfaces, or you can bind to 0.0.0.0, in which case the socket will listen on all interfaces.

If you connect an unbound socket, then the machine's routing tables, in conjunction with the destination IP adress, will determine which interface the connection request goes out on.

It is possible to bind a socket then connect it. In this case, the socket will remain bound as per the bind call when it makes the connection. (Thanks to @RemyLebeau for pointing this out.)

失退 2024-10-12 00:49:47

我不太确定哪种方法最好,但是 Shtééf 提出的 bind()-before-connect() 方法有另一种理论。它将 setsockopt() 与 SO_BINDTODEVICE 一起使用。请参阅:http://codingrelic.geekhold.com/2009/10/code -snippet-sobindtodevice.html

I'm not really sure which method is the best, but there is an alternative theory to the bind()-before-connect() approach that Shtééf presented. It's to use setsockopt() with SO_BINDTODEVICE . See: http://codingrelic.geekhold.com/2009/10/code-snippet-sobindtodevice.html

花开浅夏 2024-10-12 00:49:47

或者,您可以根据名称搜索适当的网卡:

        //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);

As an alternative, you can search for the appropriate nic based on its name:

        //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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文