Elementary TCP & UDP Sockets: System Call Lifecycles
Idea in plain words
TCP Server Call Sequence: socket() -> bind() -> listen() -> accept() -> read()/write() -> close().
Exam tip
High-yield exam topic (Very High).
Explanation
TCP and UDP sockets present distinct paradigms. Stream sockets (SOCK_STREAM) provide reliable byte-stream channels requiring explicit connection setup. The listening socket descriptor (listenfd) serves solely as a connection receptionist, while accept() yields a connected descriptor (connfd) for per-client data exchange. In contrast, Datagram sockets (SOCK_DGRAM) are connectionless. A single UDP socket can exchange datagrams with multiple distinct endpoints using recvfrom() and sendto(), which encapsulate destination addressing directly in the payload header.
Key points
- TCP Client Call Sequence: socket() -> connect() -> write()/read() -> close().
- listen(sockfd, backlog): Backlog specifies the maximum length of completed and incomplete connection queues.
- accept() blocks until a completed 3-way handshake arrives, returning a new connected socket descriptor.
- UDP Sockets use sendto() and recvfrom() without listen() or accept(); each packet specifies the destination sockaddr.
Example
Example
UDP Echo Client call pattern: socket(AF_INET, SOCK_DGRAM, 0) followed by sendto(sockfd, buf, len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) and recvfrom(sockfd, buf, len, 0, NULL, NULL).
Code examples
// Concurrent TCP Echo Server in C
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(9000);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 10);
while (1) {
struct sockaddr_in cliaddr;
socklen_t clilen = sizeof(cliaddr);
int connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
if (fork() == 0) { // Child process
close(listenfd);
char buf[1024];
int n = read(connfd, buf, sizeof(buf));
write(connfd, buf, n); // Echo
close(connfd);
exit(0);
}
close(connfd); // Parent closes connected socket
}
return 0;
}
Exam questions
- [10 Marks] Write a complete C program to implement a concurrent TCP daytime/echo server using socket(), bind(), listen(), accept(), and fork().
- [6 Marks] Compare TCP socket functions with UDP socket functions (sendto/recvfrom vs write/read).