socket connect() vs bind()

CSocketsNetwork Programming

C Problem Overview


Both connect() and bind() system calls 'associate' the socket file descriptor to an address (typically an ip/port combination). Their prototypes are like:-

int connect(int sockfd, const struct sockaddr *addr,
               socklen_t addrlen);

and

int bind(int sockfd, const struct sockaddr *addr,
            socklen_t addrlen);

What is the exact difference between 2 calls? When should one use connect() and when bind()?

Specifically, in some sample server client codes, found that client is using connect() and server is using the bind() call. Reason was not fully clear to me.

C Solutions


Solution 1 - C

To make understanding better , lets find out where exactly bind and connect comes into picture,

Further to positioning of two calls , as clarified by Sourav,

bind() associates the socket with its local address [that's why server side binds, so that clients can use that address to connect to server.] connect() is used to connect to a remote [server] address, that's why is client side, connect [read as: connect to server] is used.

We cannot use them interchangeably (even when we have client/server on same machine) because of specific roles and corresponding implementation.

I will further recommend to correlate these calls TCP/IP handshake .

enter image description here

So , who will send SYN here , it will be connect() . While bind() is used for defining the communication end point.

Hope this helps!!

Solution 2 - C

The one liner : bind() to own address, connect() to remote address.

Quoting from the man page of bind()

> bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. addrlen specifies the size, in bytes, of the address structure pointed to by addr. Traditionally, this operation is called "assigning a name to a socket".

and, from the same for connect()

> The connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.

To clarify,

  • bind() associates the socket with its local address [that's why server side binds, so that clients can use that address to connect to server.]
  • connect() is used to connect to a remote [server] address, that's why is client side, connect [read as: connect to server] is used.

Solution 3 - C

bind tells the running process to claim a port. i.e, it should bind itself to port 80 and listen for incomming requests. with bind, your process becomes a server. when you use connect, you tell your process to connect to a port that is ALREADY in use. your process becomes a client. the difference is important: bind wants a port that is not in use (so that it can claim it and become a server), and connect wants a port that is already in use (so it can connect to it and talk to the server)

Solution 4 - C

I think it would help your comprehension if you think of connect() and listen() as counterparts, rather than connect() and bind(). The reason for this is that you can call or omit bind() before either, although it's rarely a good idea to call it before connect(), or not to call it before listen().

If it helps to think in terms of servers and clients, it is listen() which is the hallmark of the former, and connect() the latter. bind() can be found - or not found - on either.

If we assume our server and client are on different machines, it becomes easier to understand the various functions.

bind() acts locally, which is to say it binds the end of the connection on the machine on which it is called, to the requested address and assigns the requested port to you. It does that irrespective of whether that machine will be a client or a server. connect() initiates a connection to a server, which is to say it connects to the requested address and port on the server, from a client. That server will almost certainly have called bind() prior to listen(), in order for you to be able to know on which address and port to connect to it with using connect().

If you don't call bind(), a port and address will be implicitly assigned and bound on the local machine for you when you call either connect() (client) or listen() (server). However, that's a side effect of both, not their purpose. A port assigned in this manner is ephemeral.

An important point here is that the client does not need to be bound, because clients connect to servers, and so the server will know the address and port of the client even though you are using an ephemeral port, rather than binding to something specific. On the other hand, although the server could call listen() without calling bind(), in that scenario they would need to discover their assigned ephemeral port, and communicate that to any client that it wants to connect to it.

I assume as you mention connect() you're interested in TCP, but this also carries over to UDP, where not calling bind() before the first sendto() (UDP is connection-less) also causes a port and address to be implicitly assigned and bound. One function you cannot call without binding is recvfrom(), which will return an error, because without an assigned port and bound address, there is nothing to receive from (or too much, depending on how you interpret the absence of a binding).

Solution 5 - C

From Wikipedia http://en.wikipedia.org/wiki/Berkeley_sockets#bind.28.29

connect():

The connect() system call connects a socket, identified by its file descriptor, to a remote host specified by that host's address in the argument list.

Certain types of sockets are connectionless, most commonly user datagram protocol sockets. For these sockets, connect takes on a special meaning: the default target for sending and receiving data gets set to the given address, allowing the use of functions such as send() and recv() on connectionless sockets.

connect() returns an integer representing the error code: 0 represents success, while -1 represents an error.

bind():

bind() assigns a socket to an address. When a socket is created using socket(), it is only given a protocol family, but not assigned an address. This association with an address must be performed with the bind() system call before the socket can accept connections to other hosts. bind() takes three arguments:

sockfd, a descriptor representing the socket to perform the bind on. my_addr, a pointer to a sockaddr structure representing the address to bind to. addrlen, a socklen_t field specifying the size of the sockaddr structure. Bind() returns 0 on success and -1 if an error occurs.

Examples: 1.)Using Connect

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(){
  int clientSocket;
  char buffer[1024];
  struct sockaddr_in serverAddr;
  socklen_t addr_size;

  /*---- Create the socket. The three arguments are: ----*/
  /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
  clientSocket = socket(PF_INET, SOCK_STREAM, 0);
  
  /*---- Configure settings of the server address struct ----*/
  /* Address family = Internet */
  serverAddr.sin_family = AF_INET;
  /* Set port number, using htons function to use proper byte order */
  serverAddr.sin_port = htons(7891);
  /* Set the IP address to desired host to connect to */
  serverAddr.sin_addr.s_addr = inet_addr("192.168.1.17");
  /* Set all bits of the padding field to 0 */
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  

  /*---- Connect the socket to the server using the address struct ----*/
  addr_size = sizeof serverAddr;
  connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

  /*---- Read the message from the server into the buffer ----*/
  recv(clientSocket, buffer, 1024, 0);

  /*---- Print the received message ----*/
  printf("Data received: %s",buffer);   

  return 0;
}

2.)Bind Example:

int main()
{
	struct sockaddr_in source, destination = {};  //two sockets declared as previously
	int sock = 0;
	int datalen = 0;
	int pkt = 0;

	uint8_t *send_buffer, *recv_buffer;
	
	struct sockaddr_storage fromAddr;	// same as the previous entity struct sockaddr_storage serverStorage;
	unsigned int addrlen;  //in the previous example socklen_t addr_size;
	struct timeval tv;
	tv.tv_sec = 3;  /* 3 Seconds Time-out */
	tv.tv_usec = 0;
	
	/* creating the socket */         
	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
		printf("Failed to create socket\n");
	
	/*set the socket options*/
	setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
	
	/*Inititalize source to zero*/
	memset(&source, 0, sizeof(source));       //source is an instance of sockaddr_in. Initialization to zero
	/*Inititalize destinaton to zero*/
	memset(&destination, 0, sizeof(destination));
	

	/*---- Configure settings of the source address struct, WHERE THE PACKET IS COMING FROM ----*/
	/* Address family = Internet */
	source.sin_family = AF_INET;    
	/* Set IP address to localhost */	
	source.sin_addr.s_addr = INADDR_ANY;  //INADDR_ANY = 0.0.0.0
	/* Set port number, using htons function to use proper byte order */
	source.sin_port = htons(7005); 
	/* Set all bits of the padding field to 0 */
	memset(source.sin_zero, '\0', sizeof source.sin_zero); //optional
	
	
	/*bind socket to the source WHERE THE PACKET IS COMING FROM*/
	if (bind(sock, (struct sockaddr *) &source, sizeof(source)) < 0) 
		printf("Failed to bind socket");
		
	/* setting the destination, i.e our OWN IP ADDRESS AND PORT */
	destination.sin_family = AF_INET;                 
	destination.sin_addr.s_addr = inet_addr("127.0.0.1");  
	destination.sin_port = htons(7005); 
	
	//Creating a Buffer;
	send_buffer=(uint8_t *) malloc(350);
	recv_buffer=(uint8_t *) malloc(250);
	  	
	addrlen=sizeof(fromAddr);
	
	memset((void *) recv_buffer, 0, 250);
	memset((void *) send_buffer, 0, 350);
	
	sendto(sock, send_buffer, 20, 0,(struct sockaddr *) &destination, sizeof(destination));

	pkt=recvfrom(sock, recv_buffer, 98,0,(struct sockaddr *)&destination, &addrlen);
	if(pkt > 0)
		printf("%u bytes received\n", pkt);
	}

I hope that clarifies the difference

Please note that the socket type that you declare will depend on what you require, this is extremely important

Solution 6 - C

Too Long; Don't Read: The difference is whether the source (local) or the destination address/port is being set. In short, bind() set the source and connect() set the destination. Regardless of TCP or UDP.

bind()

bind() set the socket's local (source) address. This is the address where packets are received. Packets sent by the socket carry this as the source address, so the other host will know where to send back its packets.

If receive is not needed the socket source address is useless. Protocols like TCP require receiving enabled in order to send properly, as the destination host send back a confirmation when one or more packets have arrived (i.e. acknowledgement).

connect()

  • TCP has a "connected" state. connect() triggers the TCP code to try to establish a connection to the other side.
  • UDP has no "connected" state. connect() only set a default address to where packets are sent when no address is specified. When connect() is not used, sendto() or sendmsg() must be used containing the destination address.

When connect() or a send function is called, and no address is bound, Linux automatically bind the socket to a random port. For technical details, take a look at inet_autobind() in Linux kernel source code.

Side notes

  • listen() is TCP only.

  • In AF_INET family, the socket's source or destination address (struct sockaddr_in) is composed by an IP address (see IP header), and TCP or UDP port (see TCP and UDP header).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSiddhartha GhoshView Question on Stackoverflow
Solution 1 - CJain RachView Answer on Stackoverflow
Solution 2 - CSourav GhoshView Answer on Stackoverflow
Solution 3 - CPhilipp MurryView Answer on Stackoverflow
Solution 4 - CpjcardView Answer on Stackoverflow
Solution 5 - CKhanView Answer on Stackoverflow
Solution 6 - CRicardo Biehl PasqualiView Answer on Stackoverflow