TCP服务器和客户端编程步骤详解
一、TCP服务器编程步骤
1. 创建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- 功能:创建TCP套接字
- 参数:
AF_INET:IPv4地址族
SOCK_STREAM:面向连接的流式套接字(TCP)
0:默认协议
- 返回值:套接字文件描述符,失败返回-1
2. 初始化服务器地址结构
struct sockaddr_in Ssocksddr;
memset(&Ssocksddr, 0, sizeof(Ssocksddr));
Ssocksddr.sin_family = AF_INET;
Ssocksddr.sin_addr.s_addr = inet_addr("192.168.126.130");
Ssocksddr.sin_port = htons(6543);
- 功能:设置服务器IP和端口
- 关键函数:
inet_addr():将点分十进制IP转换为网络字节序
htons():将主机字节序端口转换为网络字节序
3. 绑定地址
int n = bind(sockfd, (struct sockaddr*)&Ssocksddr, sizeof(Ssocksddr));
- 功能:将套接字与服务器地址绑定
- 参数:监听套接字、服务器地址结构、结构体大小
4. 开始监听
n = listen(sockfd, 5);
- 功能:将套接字设为监听状态,等待客户端连接
- 参数:
backlog=5表示已完成三次握手的连接队列最大长度
5. 接受客户端连接
int len = sizeof(Csocksddr);
int newsocked = accept(sockfd, (struct sockaddr*)&Csocksddr, &len);
- 功能:从连接队列中取出一个客户端连接
- 返回值:新的连接套接字,专门用于与该客户端通信
- 注意:
accept()会阻塞直到有客户端连接
6. 数据收发循环
// 接收数据
int n = recv(newsocked, buffer, 127, 0);
// 发送数据
send(newsocked, "Yes\n", 4, 0);
- 功能:与客户端进行数据通信
- recv参数:
newsocked:连接套接字
buffer:接收缓冲区
127:最大接收字节数
0:默认标志
7. 关闭连接
close(newsocked);
二、TCP客户端编程步骤
1. 创建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
2. 初始化服务器地址结构
struct sockaddr_in Ssock;
memset(&Ssock, 0, sizeof(Ssock));
Ssock.sin_family = AF_INET;
Ssock.sin_addr.s_addr = inet_addr("127.0.0.1");
Ssock.sin_port = htons(6543);
3. 连接服务器
int n = connect(sockfd, (struct sockaddr*)&Ssock, sizeof(Ssock));
- 功能:主动向服务器发起连接请求
- 触发:自动完成TCP三次握手过程
4. 数据收发循环
// 获取用户输入
fgets(buffer, 128, stdin);
// 发送数据到服务器
send(sockfd, buffer, strlen(buffer)-1, 0);
// 接收服务器回复
recv(sockfd, buffer, 127, 0);
- 注意:
strlen(buffer)-1是为了去掉fgets读取的换行符
5. 关闭连接
close(sockfd);
三、关键概念回顾
套接字类型
- 监听套接字:由
socket()创建,用于listen()和accept()
- 连接套接字:由
accept()返回,用于与特定客户端通信
字节序转换
htons():主机到网络短整型(端口)
inet_addr():字符串IP到网络字节序
核心函数对比
| 函数 |
服务器 |
客户端 |
功能 |
| socket() |
✓ |
✓ |
创建套接字 |
| bind() |
✓ |
✗ |
绑定地址 |
| listen() |
✓ |
✗ |
开始监听 |
| accept() |
✓ |
✗ |
接受连接 |
| connect() |
✗ |
✓ |
连接服务器 |
| send()/recv() |
✓ |
✓ |
数据收发 |
| close() |
✓ |
✓ |
关闭连接 |