套接字

套接字(Sockets)

什么是套接字?

套接字(Socket)是网络编程的基础,它是进程间通信的一种机制,允许不同主机上的进程进行通信。套接字提供了一个通用的接口,用于通过网络进行数据传输。

套接字类型

1. 流套接字(SOCK_STREAM)

  • 提供面向连接的、可靠的数据传输

  • 使用TCP协议

  • 保证数据顺序和完整性

  • 适用于文件传输、网页浏览等

2. 数据报套接字(SOCK_DGRAM)

  • 提供无连接的、不可靠的数据传输

  • 使用UDP协议

  • 不保证数据顺序和完整性

  • 适用于视频流、实时游戏等

3. 原始套接字(SOCK_RAW)

  • 提供对底层网络协议的访问

  • 需要root权限

  • 适用于网络诊断、协议开发

基本套接字操作

// 创建套接字
int socket_fd = socket(domain, type, protocol);

// 绑定地址
bind(socket_fd, (struct sockaddr*)&address, sizeof(address));

// 监听连接(服务器)
listen(socket_fd, backlog);

// 接受连接(服务器)
int client_fd = accept(socket_fd, NULL, NULL);

// 连接服务器(客户端)
connect(socket_fd, (struct sockaddr*)&address, sizeof(address));

// 发送数据
send(socket_fd, buffer, buffer_size, 0);

// 接收数据
recv(socket_fd, buffer, buffer_size, 0);

// 关闭套接字
close(socket_fd);

地址族

  • AF_INET - IPv4地址族

  • AF_INET6 - IPv6地址族

  • AF_UNIX - UNIX域套接字

  • AF_NETLINK - 内核用户接口

  • AF_PACKET - 底层包接口

套接字选项

// 设置套接字选项
int optval = 1;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

// 设置超时
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

常见错误处理

  • ECONNREFUSED - 连接被拒绝

  • ETIMEDOUT - 连接超时

  • ECONNRESET - 连接被重置

  • ENOTCONN - 套接字未连接

UNIX域套接字

UNIX域套接字特点

UNIX域套接字(UNIX Domain Sockets)是一种特殊的套接字,用于同一主机上的进程间通信。

优势

  • 高性能:不经过网络栈,直接在内核中传递数据

  • 安全性:基于文件系统权限

  • 可靠性:保证数据传输的完整性

  • 低延迟:没有网络开销

使用场景

  • 本地服务通信

  • 数据库连接

  • IPC(进程间通信)

  • 微服务架构

创建UNIX域套接字

// 创建UNIX域套接字
int fd = socket(AF_UNIX, SOCK_STREAM, 0);

// 设置地址结构
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/socket_file");

// 绑定地址
bind(fd, (struct sockaddr*)&addr, sizeof(addr));

// 监听和接受连接
listen(fd, 5);
int client_fd = accept(fd, NULL, NULL);

文件权限

UNIX域套接字的权限由文件系统权限控制:

# 设置套接字权限
$ chmod 660 /tmp/socket_file
$ chown user:group /tmp/socket_file

客户端连接

// 客户端连接
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/socket_file");
connect(fd, (struct sockaddr*)&addr, sizeof(addr));

套接字最佳实践

  1. 错误处理:始终检查系统调用的返回值

  2. 资源管理:正确关闭套接字,避免资源泄漏

  3. 超时设置:为网络操作设置合理的超时时间

  4. 缓冲区管理:正确处理部分发送/接收的情况

  5. 并发处理:使用多线程或I/O多路复用处理并发连接

参考资料

最后更新于