C++ TCP通信原理与实现
C++ 中 TCP 通信的原理基于 TCP/IP 协议栈的实现,以下是核心原理和关键步骤的详细说明:
一、TCP 通信核心原理
-
面向连接
- 通信双方需通过 三次握手 建立可靠连接,确保通信通道稳定。
- 通过 四次挥手 断开连接,保证数据完整性。
-
可靠传输
- 确认应答(ACK):接收方对收到的数据发送确认。
- 超时重传:未收到 ACK 时,发送方自动重传数据。
- 数据排序:通过序列号保证数据按序到达。
-
流量控制与拥塞控制
- 滑动窗口协议动态调整发送速率,避免接收方缓冲区溢出。
- 拥塞控制算法(如慢启动、拥塞避免)防止网络过载。
二、C++ 实现 TCP 通信的步骤
1. 服务器端流程
#include <sys/socket.h>
#include <netinet/in.h>int main() {// 1. 创建套接字int server_fd = socket(AF_INET, SOCK_STREAM, 0);// 2. 绑定地址和端口struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = INADDR_ANY; // 绑定所有网卡addr.sin_port = htons(8080); // 端口号bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));// 3. 监听连接listen(server_fd, 5); // 最大等待队列长度// 4. 接受客户端连接int client_fd;struct sockaddr_in client_addr;socklen_t client_len = sizeof(client_addr);client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);// 5. 收发数据char buffer[1024];recv(client_fd, buffer, sizeof(buffer), 0); // 接收数据send(client_fd, "Hello Client", 12, 0); // 发送数据// 6. 关闭连接close(client_fd);close(server_fd);
}
2. 客户端流程
#include <sys/socket.h>
#include <arpa/inet.h>int main() {// 1. 创建套接字int sock = socket(AF_INET, SOCK_STREAM, 0);// 2. 连接服务器struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8080);inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); // 服务器IPconnect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));// 3. 收发数据send(sock, "Hello Server", 12, 0);recv(sock, buffer, sizeof(buffer), 0);// 4. 关闭连接close(sock);
}
三、关键函数说明
-
socket()
- 创建套接字,返回文件描述符。
- 参数:
AF_INET
(IPv4)、SOCK_STREAM
(TCP)。
-
bind()
- 将套接字绑定到特定 IP 和端口。
-
listen()
- 进入监听状态,等待客户端连接请求。
-
accept()
- 阻塞等待客户端连接,返回新的套接字用于通信。
-
connect()
- 客户端主动连接服务器。
-
send()
/recv()
- 发送和接收数据(注意处理粘包问题)。
-
close()
- 关闭套接字,释放资源。
四、注意事项
-
错误处理
- 所有函数调用需检查返回值(如
socket()
返回-1
表示失败)。
- 所有函数调用需检查返回值(如
-
字节序转换
- 使用
htons()
、htonl()
转换网络字节序(大端模式)。
- 使用
-
粘包问题
- 需自定义协议(如消息头包含数据长度)处理 TCP 的流式特性。
-
跨平台差异
- Windows 使用
WSAStartup()
初始化 Winsock,Linux 无需此步骤。
- Windows 使用
五、总结
TCP 通信通过三次握手建立可靠连接,利用序列号、ACK 确认和重传机制保证数据可靠传输。在 C++ 中,通过套接字 API 实现服务端和客户端的通信逻辑,需注意错误处理、字节序转换及粘包问题。实际开发中可借助 Boost.Asio 或 libevent 等库简化操作。