Linux下的Socket编程基础
Socket(套接字)是Linux网络编程的核心,它提供了不同主机间进程通信的机制,通过Socket,开发者可以实现客户端-服务器架构的应用,如Web服务、即时通讯等,本文将介绍Linux下Socket编程的基本概念、常用函数、通信流程及实例分析。

Socket概述与类型
Socket起源于Unix系统,最初用于进程间通信(IPC),后扩展到网络通信,在Linux中,Socket是一种文件描述符,通过系统调用创建和管理,根据通信域的不同,Socket可分为多种类型:
- AF_INET(IPv4):用于网络通信,基于TCP/IP协议族。
- AF_INET6(IPv6):支持IPv6协议的网络通信。
- AF_UNIX:同一主机进程间通信,基于文件系统路径。
- AF_PACKET:直接与网络层交互,支持原始数据包操作。
AF_INET是最常用的类型,配合SOCK_STREAM(TCP)或SOCK_DGRAM(UDP)实现可靠或不可靠的数据传输。
Socket编程基本流程
Socket编程的核心流程包括创建Socket、绑定地址、监听连接、接受请求、数据传输及关闭连接,以下以TCP为例,分步骤说明:
创建Socket
使用socket()函数创建Socket:
int socket(int domain, int type, int protocol);
domain:指定通信域(如AF_INET)。type:指定类型(SOCK_STREAM或SOCK_DGRAM)。protocol:通常设为0,表示自动选择协议。
成功时返回Socket文件描述符,失败返回-1。
绑定地址
服务器端需绑定IP和端口,使用bind()函数:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:Socket描述符。addr:指向sockaddr结构的指针,包含IP和端口信息。addrlen:地址结构长度。
监听连接
TCP服务器需调用listen()进入监听状态:
int listen(int sockfd, int backlog);
backlog:最大等待连接数。
接受连接
使用accept()接受客户端连接:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
成功时返回新的Socket描述符,用于后续数据传输。
数据传输
通过send()和recv()(或write()/read())传输数据:
ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags);
关闭连接
调用close()关闭Socket:
int close(int sockfd);
UDP Socket编程特点
UDP是无连接协议,编程流程更为简洁:

- 创建Socket(
SOCK_DGRAM)。 - 绑定地址(可选,客户端通常无需绑定)。
- 使用
sendto()和recvfrom()直接收发数据:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
错误处理与优化
Socket编程中需关注错误处理,如perror()打印错误信息,errno获取错误码,常见问题包括:
- 地址占用(EADDRINUSE):端口被占用,需修改或等待释放。
- 连接拒绝(ECONNREFUSED):服务器未启动或端口错误。
- 超时设置:使用
setsockopt()设置SO_RCVTIMEO和SO_SNDTIMEO避免阻塞。
性能优化方面,可通过多线程(pthread)、多进程(fork)或I/O多路复用(select、poll、epoll)提高并发处理能力。epoll是Linux下高效的I/O多路复用机制,适合高并发场景。
实例分析:简单回显服务器
以下是一个基于TCP的回显服务器示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
// 创建Socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置端口复用
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// 绑定地址
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听连接
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 接收并回发数据
read(new_socket, buffer, BUFFER_SIZE);
printf("Message from client: %s\n", buffer);
send(new_socket, buffer, strlen(buffer), 0);
close(new_socket);
close(server_fd);
return 0;
}
Linux下的Socket编程是网络应用开发的基础,掌握其原理和流程至关重要,从基础的TCP/UDP通信到高级的I/O多路复用,开发者需结合实际场景选择合适的技术,通过不断实践和优化,可以构建高效、稳定的网络服务。



















