2. TCP客户端连接
任务说明
本案例要求编写一个TCP客户端程序,实现以下功能:主动连接指定的服务器地址和端口,连接建立后向服务器发送一段数据,并接收服务器返回的数据,最后关闭连接。通过本案例掌握Linux下socket编程中connect()、send()和recv()三个核心函数的使用方法。
实现方案
客户端程序采用以下流程:创建socket → 设置服务器地址结构 → 调用connect()建立连接 → 调用send()发送数据 → 调用recv()接收服务器响应 → 关闭socket。程序支持通过命令行参数指定服务器IP和端口,默认连接本机8888端口。为保证可复现性,代码中内置了默认的测试服务器地址(127.0.0.1:8888),并允许用户覆盖。
完整代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
const char *server_ip = "127.0.0.1";
int server_port = 8888;
// 解析命令行参数:./tcp_client [server_ip] [server_port]
if (argc > 1) server_ip = argv[1];
if (argc > 2) server_port = atoi(argv[2]);
// 1. 创建socket
int client_fd = socket(AF_INET, SOCK_STREAM, 0);
if (client_fd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
// 2. 配置服务器地址
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
if (inet_pton(AF_INET, server_ip, &server_addr.sin_addr) <= 0) {
perror("inet_pton");
close(client_fd);
exit(EXIT_FAILURE);
}
// 3. 连接服务器
if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("connect");
close(client_fd);
exit(EXIT_FAILURE);
}
printf("已连接到 %s:%d\n", server_ip, server_port);
// 4. 发送数据
const char *message = "Hello, TCP Server!";
ssize_t send_len = send(client_fd, message, strlen(message), 0);
if (send_len < 0) {
perror("send");
close(client_fd);
exit(EXIT_FAILURE);
}
printf("已发送 %zd 字节: %s\n", send_len, message);
// 5. 接收服务器响应
char buffer[BUFFER_SIZE];
memset(buffer, 0, sizeof(buffer));
ssize_t recv_len = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
if (recv_len < 0) {
perror("recv");
close(client_fd);
exit(EXIT_FAILURE);
} else if (recv_len == 0) {
printf("服务器已关闭连接\n");
} else {
buffer[recv_len] = '\0';
printf("收到 %zd 字节: %s\n", recv_len, buffer);
}
// 6. 关闭连接
close(client_fd);
printf("连接已关闭\n");
return 0;
}
编译与运行
将上述代码保存为tcp_client.c,使用gcc编译:
gcc -o tcp_client tcp_client.c
运行客户端前需要有一个TCP服务器在监听。可以使用Linux自带的nc命令快速启动一个测试服务器:
# 终端1:启动监听服务器
nc -l 8888
# 终端2:运行客户端(默认连接127.0.0.1:8888)
./tcp_client
也可以指定其他服务器地址和端口:
./tcp_client 192.168.1.100 9000
验证方法与判定标准
1. 连接成功验证:客户端输出已连接到 127.0.0.1:8888,同时nc终端显示有连接接入。
2. 数据发送验证:客户端输出已发送 18 字节: Hello, TCP Server!,nc终端应显示收到的原始字符串Hello, TCP Server!。
3. 数据接收验证:在nc终端输入任意回复内容(如Hello, Client!)并回车,客户端应输出收到 N 字节: Hello, Client!。
4. 关闭验证:客户端输出连接已关闭,nc终端显示连接断开。
5. 异常路径验证:在不启动服务器的情况下运行客户端,应输出connect: Connection refused错误信息并退出。
关键函数说明
connect()用于将socket与服务器地址绑定并建立TCP连接,阻塞直到握手完成或超时失败。send()在已连接的socket上发送数据,返回实际发送的字节数。recv()接收对端数据,返回接收字节数,返回0表示对端已关闭连接。三个函数失败时均返回-1,需检查errno获取具体错误原因。本案例代码中已包含完整的错误处理路径,确保每个系统调用失败时都能输出明确提示并安全退出。