62

I wanted to know the exact function of bind() in TCP. What does it mean by 'binding' a local address to the socket? If it's assigning a port number to the socket, then why don't we use it in the client? I know that port is assigned by OS automatically in the client side, but I'm not getting the big picture of how all of this works.

After bind(), we listen(). How is the bind related to listen()? Will the listen() know that bind() has been executed? If so, what changes does bind() make so that it is known? I mean, how does returning zero for successful execution help?

I've gone through many definitions, but no where I could get all of this in detail. So if anyone can please explain this to me, I will be grateful.

Ajay
  • 18,086
  • 12
  • 59
  • 105
Crocode
  • 3,056
  • 6
  • 26
  • 31

4 Answers4

32

It assigns the "local" end's port number.

For a server socket, this is the ultimate way to go - it is exactly what is needed: have your socket be bound to port 80 for a web server, for example.

For a client socket, however, the local address and port is normally not of importance. So you don't bind(). If the server restricts its clients to maybe have a certain port number, or a port number out of a given range, you can use bind() on client side as well.

On the other hand, you might as well be able to listen() on a socket where you haven't called bind() (actually I'm not sure about that, but it would make sense). In this scenario, your server port would be random, and the server process would communicate its port via a different means to the client. Imagine a "double-connection" protocol such as FTP, where you have a control connection and a data connection. The port the data connection listens on is completely arbitrary, but must be communicated to the other side. So the "automatically determined port" is used and communicated.

One example in Python:

import socket
s = socket.socket() # create your socket
s.listen(10) # call listen without bind
s.getsockname() Which random port number did we get?
# here results in ('0.0.0.0', 61372)

s2 = socket.socket() # create client socket
s2.connect(('localhost', 61372)) # connect to the one above
s3, x = s.accept() # Python specific use; s3 is our connected socket on the server side
s2.getpeername()
# gives ('127.0.0.1', 61372)
s2.getsockname()
# gives ('127.0.0.1', 54663)
s3.getsockname()
# gives ('127.0.0.1', 61372), the same as s2.getpeername(), for symmetry
s3.getpeername()
#gives ('127.0.0.1', 54663), the same as s2.getsockname(), for symmetry
#test the connection
s2.send('hello')
print s3.recv(10)
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • 4
    this answer is incomplete as it is also responsible for which network interfaces to listen on via an ip address e.g. `0.0.0.0` – user3338098 Nov 04 '15 at 17:54
18

bind() defines the local port and interface address for the connection. connect() does an implicit bind("0.0.0.0", 0) if one has not been done previously (with zero being taken as "any").

For outgoing connections, this is generally acceptable and preferred. The OS will simply bind to "all interfaces" and pick some high-numbered, unused port. You only need to bind on the client if the server expects you to be coming from a specific port or port range. Some services only allow connections from port numbers less than 1024, those only bindable by the superuser, though that doesn't mean much these days now that everyone controls their own machine.

For incoming connections, you have to bind to a known port so clients know where to contact you. Once they do so, they've given the server their local address/port so that communication can then flow in both directions. listen() will only work after a bind() call.

All sockets must bind, whether they be UDP, TCP, or other. It's just not always explicitly done.

Brian White
  • 8,332
  • 2
  • 43
  • 67
  • 2
    "`listen()` will only work after a `bind()` call." No, as you can see in [my example](http://stackoverflow.com/a/12763313/296974). – glglgl Oct 08 '12 at 04:59
  • 3
    If it works, then the `bind()` is implicit and picks a semi-random port number bound to all interfaces. This is not generally useful (though there are rare exceptions). – Brian White Oct 09 '12 at 00:35
  • Brian White is right as the `connect()` does the implicit bind (otherwise, the kernel wouldn't know how to connect without reserving the resources locally first). – Eric L. May 19 '20 at 23:28
  • @BrianWhite "The OS will simply bind to 'all interfaces'" What do you mean by that? As per my understanding, the sent packet will contain one source IP address. The client can't send packets containing every IP address of each of its interface as the source IP address. – Mehdi Charife Nov 21 '22 at 00:14
  • It means that it will _accept_ packets from all interfaces. Outgoing packets will have the "source" IP address of the interface out which the packets travel which will be the same interface upon which packets for that connection arrive. – Brian White Nov 28 '22 at 14:22
11

It "binds" a socket to an address, otherwise it doesn't know what address (ip-address/port pair) it should listen to.

And bind can be used on the client side as well. One example is on a computer with multiple network cards connected to the same network, but the client only want to be seen as coming from one specific network address.

Binding is not only used for TCP sockets, but for UDP sockets as well, and other protocols too.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I believe the you're referring to "bonding" when describing the example for the client side. This is different than a IP Address/Port Number bind. Network Interface Card (NIC) bonding (also known as teaming) enables you to join two NICs as a single physical device so that they appear as one interface. – Jboullianne Feb 10 '22 at 16:29
1

I know this is an old question, but I have a new answer :)

You might want to connect to a server which only allows a limited number of incoming connections per ip.

If you have several network interface cards (and thus multiple possible outgoing ips to connect from), you can use bind(), manuallying cycling through each of your ips, in order to balance your connections, and thus have several times as many connections as would be otherwise allowed.

To get a list of your interfaces and ips, see this answer.

BenGoldberg
  • 415
  • 3
  • 6