Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a socket know which network interface controller to use?

People also ask

How is a socket identified in network communication?

A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to. An endpoint is a combination of an IP address and a port number. Every TCP connection can be uniquely identified by its two endpoints.

How does a network interface controller work?

A NIC provides a computer with a dedicated, full-time connection to a network. It implements the physical layer circuitry necessary for communicating with a data link layer standard, such as Ethernet or Wi-Fi. Each card represents a device and can prepare, transmit and control the flow of data on the network.

What is socket interface in networking?

A socket has a type and one associated process. Sockets were designed to implement the client-server model for interprocess communication where: The interface to network protocols needs to accommodate multiple communication protocols, such as TCP/IP, Xerox internet protocols (XNS), and UNIX family.

How are sockets identified?

A socket is identified by: (Local IP,Local Port, Remote IP, Remote Port,IP Protocol(UDP/TCP/SCTP/etc.) And that's the information the OS uses to map the packets/data to the right handle/file descriptor of your program.


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.


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.)


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


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