文章目录
TCP服务端
基础服务端
c
// 基础TCP服务器核心流程
#define BUFFER_SIZE 1024 // 根据设备内存自定义
char buf[BUFFER_SIZE];
int main() {
// 1. 创建socket
fd = socket(AF_INET, SOCK_STREAM, 0);
// 2. 准备地址结构
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = 0; // INADDR_ANY的另一种写法
// 3. 绑定地址
bind(fd, (struct sockaddr *)&addr, sizeof(addr));
// 4. 开始监听
listen(fd, BACKLOG);
// 5. 接受连接(阻塞等待)
newfd = accept(fd, NULL, NULL); // 不关心客户端地址
// 6. 接收数据
read(newfd, buf, BUFFER_SIZE);
// 7. 关闭连接
close(newfd);
close(fd);
return 0;
}
TCP服务设计模式
迭代服务(一次处理一个客户端)
c
// 简化的迭代服务器框架
while (1) {
client_fd = accept(server_fd, NULL, NULL);
if (client_fd < 0) continue;
handle_client(client_fd); // 处理客户端请求
close(client_fd); // 处理完后关闭
}
缺点:无法并发处理多个客户端
多进程并发服务
c
// 父进程:监听连接,创建子进程处理
// 子进程:处理具体客户端请求,结束后退出
pid_t pid = fork();
if (pid == 0) {
// 子进程
close(server_fd); // 关闭不需要的监听socket
handle_client(client_fd);
close(client_fd);
exit(0); // 子进程结束
} else {
// 父进程
close(client_fd); // 父进程关闭已分发的客户端socket
waitpid(-1, NULL, WNOHANG); // 非阻塞回收子进程
}
僵尸进程处理(信号处理)
c
// 使用信号处理函数回收子进程
void sigchld_handler(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0) {
// 回收所有已终止的子进程
}
}
// 注册信号处理器
signal(SIGCHLD, sigchld_handler);
// 更推荐使用sigaction(可重启系统调用)
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
sigaction(SIGCHLD, &sa, NULL);
多线程并发服务
c
// 主线程:监听连接,创建子线程
// 工作线程:处理客户端请求
void *client_handler(void *arg) {
int client_fd = *(int *)arg;
// 处理客户端...
close(client_fd);
return NULL;
}
// 创建线程处理每个客户端
pthread_t tid;
int *client_fd_ptr = malloc(sizeof(int));
*client_fd_ptr = client_fd;
pthread_create(&tid, NULL, client_handler, client_fd_ptr);
pthread_detach(tid); // 分离线程,自动回收资源
嵌入式设备线程注意
c
// 1. 设置线程栈大小(嵌入式内存有限)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 8192); // 8KB栈空间
// 2. 线程池模式(避免频繁创建销毁线程)
// 3. 注意线程安全,共享数据加锁
TCP客户端
基础客户端
c
// 核心流程
int main() {
// 1. 创建socket
fd = socket(AF_INET, SOCK_STREAM, 0);
// 2. 设置服务器地址
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 3. 连接服务器
connect(fd, (struct sockaddr *)&addr, sizeof(addr));
// 4. 发送数据
write(fd, STR, sizeof(STR));
// 5. 关闭连接
close(fd);
}
交互式客户端
c
// 支持命令行参数和交互式输入
int main(int argc, char *argv[]) {
// 检查参数
if (argc < 3) {
fprintf(stderr, "用法: %s <IP地址> <端口>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 解析参数
char *server_ip = argv[1];
int server_port = atoi(argv[2]);
// 创建socket和连接...
// 交互循环
while (1) {
printf("请输入消息: ");
fgets(buf, BUFSIZ, stdin);
// 发送数据
int n = write(fd, buf, strlen(buf));
if (n <= 0) {
perror("发送失败");
break;
}
// 可选:接收服务器响应
// n = read(fd, response, sizeof(response));
}
}
客户端断线重连机制
c
// 嵌入式设备常用,增加连接稳定性
#define MAX_RETRY 5
#define RETRY_DELAY 3 // 秒
int connect_with_retry(const char *ip, int port, int max_retry) {
int sockfd;
struct sockaddr_in addr;
for (int retry = 0; retry < max_retry; retry++) {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("创建socket失败");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, ip, &addr.sin_addr);
if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
printf("连接成功(第%d次尝试)\n", retry + 1);
return sockfd;
}
close(sockfd);
printf("连接失败,%d秒后重试...\n", RETRY_DELAY);
sleep(RETRY_DELAY);
}
fprintf(stderr, "连接失败,达到最大重试次数\n");
return -1;
}