In socket programming, the listen() and accept() functions play a crucial role, particularly in establishing and managing client connection requests for TCP servers. Below, I will explain the functions and their differences.
listen() Function
The listen() function is primarily used on the TCP server side. After the socket has been created using socket() and bound to a local address using bind(), the listen() function enables the socket to accept incoming client connection requests.
- Parameters: The
listen()function typically accepts two parameters: the socket descriptor and backlog. The backlog parameter defines the maximum number of pending client connections that can be queued. - Function: After calling
listen(), the previously active socket becomes passive, meaning it can accept incoming client connection requests but does not initiate connections itself.
accept() Function
After the server calls listen(), the accept() function is used to accept a client connection request from the established queue.
- Parameters: The
accept()function typically accepts three parameters: the listening socket descriptor, a pointer tostruct sockaddrfor retrieving client address information, and the size of the address structure. - Function: The
accept()function blocks the current process until a client connection request arrives. Once the client connection is established,accept()returns a new socket descriptor for communication with the newly connected client. The original socket remains in thelisten()state, accepting other connection requests.
Differences
In summary, the main differences between listen() and accept() are as follows:
- Target:
listen()acts on an unconnected socket to enable it to accept connection requests, whileaccept()actually accepts a connection request from the listening queue. - Return Value:
listen()does not return connection-related information;accept()returns a new socket descriptor for subsequent data exchange. - Function:
listen()merely prepares the socket to accept connection requests without participating in actual data transmission;accept()initiates a new session for specific data transmission.
Example
Suppose we are creating a simple TCP server. We first create and bind the socket, then call listen() to put the socket into passive listening mode. When a client attempts to connect, we use accept() to accept the connection request and communicate with the client using the returned new socket descriptor.
cint sockfd, new_sockfd; // Socket descriptors struct sockaddr_in host_addr, client_addr; // Address structures socklen_t sin_size; int yes = 1; sockfd = socket(PF_INET, SOCK_STREAM, 0); // Create socket host_addr.sin_family = AF_INET; // Host byte order host_addr.sin_port = htons(12345); // Network byte order port number host_addr.sin_addr.s_addr = INADDR_ANY; // Auto-fill IP memset(&(host_addr.sin_zero), '\0', 8); // Clear remaining parts of the structure bind(sockfd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr)); // Bind address listen(sockfd, 5); // Start listening, queue length of 5 sin_size = sizeof(struct sockaddr_in); new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size); // Accept connection request
Through this example, we can see the roles and differences of listen() and accept() in establishing a TCP server.