多进程实现高并发服务器
# server
/* 多进程实现并发服务器 主进程负责接收 子进程负责处理 */ #include <stdio.h> #include <arpa/inet.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <wait.h> #include <signal.h> #include <errno.h> void callback(int num) { // 防止终止了多个进程,未决信号集只保存了一个信号 while(1) { int ret = waitpid(-1, NULL, WNOHANG); if(ret == 0) // 还有子进程活着,但未终止 break; else if(ret == -1) // 所有的子进程都回收了 { break; } else { printf("%d recovery successfully\n", ret); } } } int main() { // 注册信号捕捉 struct sigaction act; act.sa_handler = callback; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGCHLD, &act, NULL); int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd == -1) { perror("socket"); exit(-1); } char *temp = "192.168.248.128"; int inet_ip; struct sockaddr_in saddr; saddr.sin_family = AF_INET; inet_pton(AF_INET, temp, (void *) &inet_ip); saddr.sin_addr.s_addr = inet_ip; saddr.sin_port = htons(9999); int ret = bind(lfd, (struct sockaddr *) &saddr, sizeof(saddr)); if(ret == -1) { perror("bind"); exit(-1); } ret = listen(lfd, 5); if(ret == -1) { perror("listen"); exit(-1); } int cfd_array[1024]; int cfd_cnt = 0; pid_t fork_flag; while(1) { struct sockaddr_in client_addr; int client_addr_len = sizeof(client_addr); int cfd = accept(lfd, (struct sockaddr *) &client_addr, (void *) &client_addr_len); if(cfd == -1) { if(errno == EINTR) continue; perror("accept"); exit(-1); } cfd_array[cfd_cnt++] = cfd; fork_flag = fork(); if(fork_flag == -1) { perror("fork"); exit(-1); } else if(fork_flag == 0) { char clientIP[16]; inet_ntop(AF_INET, (void *)&client_addr.sin_addr.s_addr, clientIP, sizeof(clientIP)); unsigned short clientPORT = ntohs(client_addr.sin_port); printf("client ip is %s, port is %d\n", clientIP, clientPORT); char recvBuf[1024] = {0}; int recvlen = read(cfd, recvBuf, sizeof(recvBuf)); if(recvlen == -1) { perror("read"); exit(-1); } else if(recvlen == 0) { printf("客户端断开连接······\n"); // 如果循环发送接收,这个地方要加 break } else { printf("recv client data: %s\n", recvBuf); } // 给客户端发送数据 char *data = "hello, i am server"; int len = write(cfd, data, strlen(data)); if(len == -1) { perror("write"); exit(-1); } break; } else if(fork_flag > 0) { continue; } } for(int i = 0; i < cfd_cnt; i++) close(cfd_array[i]); close(lfd); // if(fork_flag > 0) // { // while(1) // { // ret = waitpid(-1, NULL, WNOHANG); // if(ret == 0) // break; // else // { // printf("%d recovery successfully\n", ret); // } // } // } return 0; }
# client
#include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> int main() { int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd == -1) { perror("socket"); exit(-1); } char temp[] = "192.168.248.128"; int serverIP; inet_pton(AF_INET, temp, (void *)&serverIP); struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = serverIP; saddr.sin_port = htons(9999); int ret = connect(lfd, (struct sockaddr *)&saddr, sizeof(saddr)); if(ret == -1) { perror("connect"); exit(-1); } char buf[] = "hi, i am client"; write(lfd, buf, strlen(buf)); // 读取客户端发送的数据 char recvBuf[1024] = {0}; int len = read(lfd, recvBuf, sizeof(recvBuf)); if(len == -1) { perror("read"); exit(-1); } else if(len == 0) { printf("服务端断开连接······\n"); } else { printf("recv server data: %s\n", recvBuf); } close(lfd); return 0; }
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理