Understanding Sockets: Concepts, TCP/UDP, System Calls, and Sample C Code
This article explains the fundamentals of sockets as a network communication abstraction, covering process communication, TCP/UDP protocols, socket descriptors, key system calls, the TCP three‑way handshake and four‑way termination, Linux kernel basics, and provides complete C examples for a server and client.
Socket is an abstract concept for network communication that provides a programming interface allowing applications to exchange data across machines. A socket endpoint consists of an IP address and a port number, enabling client‑server bidirectional communication by establishing a connection.
Inter‑process communication (IPC) on a single host uses mechanisms such as pipes, named pipes, signals, messages, shared memory, and semaphores. Networked IPC requires unique identification of processes across hosts, which is achieved by the triple (IP address, protocol, port) defined by the TCP/IP suite.
TCP (Transmission Control Protocol) offers reliable, ordered, stream‑based transmission, while UDP (User Datagram Protocol) provides an unreliable, connectionless, low‑latency service suitable for real‑time applications.
Socket as a Facade – In Unix/Linux, a socket is a special file that implements the Facade design pattern, hiding the complexity of the TCP/IP stack behind a simple set of functions such as socket() , bind() , listen() , connect() , accept() , read() , write() , and close() .
Socket Descriptor – When a socket is created, the kernel returns a small integer (the descriptor) that uniquely identifies the socket within the process. This descriptor behaves like a file descriptor and can be used with standard I/O functions.
Key System Calls
int socket(int domain, int type, int protocol); // returns sockfd
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); // returns new connection fd
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);
The socket() call creates a descriptor; bind() assigns an address (IP + port) to it; listen() marks it as a passive listening socket; connect() initiates a client‑side connection; accept() retrieves a pending connection and returns a new descriptor for data exchange.
TCP Three‑Way Handshake – The client sends a SYN, the server replies with SYN‑ACK, and the client finalizes with ACK, establishing a reliable connection. The four‑step termination (FIN‑ACK sequence) gracefully closes the connection, handling half‑close states and TIME_WAIT.
Linux Kernel Overview – The kernel manages memory, processes, device drivers, file systems, and networking. It provides system‑call interfaces (SCI) for user‑space programs to request services such as socket creation, file I/O, and process control. The kernel separates user space (Ring 3) from kernel space (Ring 0) to ensure security.
Example: Socket Programming in C
Server (listens on port 8000, accepts connections, receives a message, and replies):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define DEFAULT_PORT 8000
#define MAXLINE 4096
int main(int argc, char** argv) {
int socket_fd, connect_fd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
int n;
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(DEFAULT_PORT);
if (bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
if (listen(socket_fd, 10) == -1) {
printf("listen socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
printf("======waiting for client's request======\n");
while (1) {
if ((connect_fd = accept(socket_fd, NULL, NULL)) == -1) {
printf("accept socket error: %s(errno: %d)", strerror(errno), errno);
continue;
}
n = recv(connect_fd, buff, MAXLINE, 0);
if (!fork()) {
if (send(connect_fd, "Hello, you are connected!\n", 26, 0) == -1)
perror("send error");
close(connect_fd);
exit(0);
}
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
close(connect_fd);
}
close(socket_fd);
}Client (connects to a given IP, sends a line of text, and prints the server's reply):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXLINE 4096
int main(int argc, char** argv) {
int sockfd, n, rec_len;
char sendline[MAXLINE];
char buf[MAXLINE];
struct sockaddr_in servaddr;
if (argc != 2) {
printf("usage: ./client
\n");
exit(0);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8000);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
printf("inet_pton error for %s\n", argv[1]);
exit(0);
}
if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
printf("connect error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
printf("send msg to server: \n");
fgets(sendline, MAXLINE, stdin);
if (send(sockfd, sendline, strlen(sendline), 0) < 0) {
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
if ((rec_len = recv(sockfd, buf, MAXLINE, 0)) == -1) {
perror("recv error");
exit(1);
}
buf[rec_len] = '\0';
printf("Received : %s", buf);
close(sockfd);
exit(0);
}Utility functions such as inet_pton() convert textual IP addresses to binary form, and proper handling of byte order (host vs. network) is essential for portable socket programs.
Deepin Linux
Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.