tcp网络编程实例2—并发的多进程实现
tcp_server_mulprocess.c #include <signal.h> #include <stdio.h> #include <errno.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <sys/wait.h> #include <arpa/inet.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> //int socket(int domain, int type, int protocol); //typedef void (*sighandler_t)(int); //sighandler_t signal(int signum, sighandler_t handler); //void perror(const char *s); int socket_fd; void sig_fun(int signo) { if(signo == SIGINT){ printf("signal = %d\n",signo); close(socket_fd); exit(1); } if(signo == SIGCHLD){ printf("signal = %d\n",signo); wait(0); } } void out_addr(struct sockaddr_in *clientaddr) { int port = ntohs(clientaddr->sin_port); char ip[16]; if(inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr, ip ,16) == NULL){ perror("out_addr:"); } printf("cliet:%s(%d)\n",ip,port); } void do_service(int fd) { char buffer[512]; while(1){ /*相当于不完整管道 *如果服务器从socket中读取到的数据为0,说明客户端关闭了socket或客户端已经挂掉了(服务器读一个写端关闭了的socket) *如果服务器往读端(客户端)关闭了的socket中写数据,将会产生一个SIGPIPE的信号,并且errorno被设置为EPIPE(服务器写一个读端关闭了的socket) */ memset(buffer, 0, sizeof(buffer)); printf("start read write...\n"); size_t size; if((size = read(fd, buffer, sizeof(buffer))) < 0){ perror("read:"); break; }else if(size == 0){ break; }else{ //write(STDOUT_FILENO, buffer, sizeof(buffer)); printf("%s(%ld)\n",buffer,size); if(write(fd, buffer, sizeof(buffer)) <0 ){ if(errno == EPIPE){ break; } perror("write:"); } } } } int main(int argc,char *argv[]) { if(argc <2){ perror("argc<2:"); exit(1); } if(signal(SIGINT,sig_fun) == SIG_ERR){ perror("signal:"); exit(1); } if(signal(SIGCHLD,sig_fun) == SIG_ERR){ perror("signal sigchld:"); exit(1); } /* *1. 创建socket */ if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ perror("socket:"); exit(1); } /* *2.绑定IP地址和端口号 *int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); */ struct sockaddr_in serviceaddr; memset(&serviceaddr, 0, sizeof(serviceaddr)); serviceaddr.sin_family = AF_INET; serviceaddr.sin_port = htons(atoi(argv[1])); serviceaddr.sin_addr.s_addr = INADDR_ANY;//一台服务器上可能有多块网卡(多个IP地址) //这个宏是响应本机所有网卡(IP地址)上连接的客户端请求 if(bind(socket_fd, (struct sockaddr *)&serviceaddr, sizeof(serviceaddr)) < 0){ perror("bind:"); exit(1); }; /* *3.监听绑定的端口 *通知系统去监听来自客户端的连接请求 *(将监听到的客户端连接请求放置到对应的队列中) *第二个参数:指定队列的长度 */ if(listen(socket_fd, 10) < 0){ perror("listen:"); exit(1); } /* *4.调用accept函数从队列中获得一个客户端的连接请求 *并返回一个新的socket描述符,这个描述符和和客户端 *的连接请求对应,即和客户端对应 *如果没有客户端连接,调用此函数会阻塞,直到获得一个客户端的连接 *第二个参数:客户端的地址信息 */ struct sockaddr_in clientaddr; socklen_t clientaddr_len = sizeof(clientaddr); while(1){ int fd = accept(socket_fd, (struct sockaddr *)&clientaddr, &clientaddr_len); if(fd < 0){ perror("accept:"); continue; } /* *5.fork出子进程进行并发处理 */ pid_t pid = fork(); if(pid < 0){ perror("fork failed:"); }else if(pid == 0){ out_addr(&clientaddr); do_service(fd); /* *5.关闭socket */ close(fd); break; }else{ /* *5.关闭socket */ close(fd); //回收子进程,避免僵尸进程(注册信号) } close(fd); } return 0; }
tcp_client_mulprocess.c #include <stdio.h> #include <errno.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int main(int argc, char *argv[]) { int socket_fd; if(argc < 2){ printf("参数太少"); exit(1); } //1.创建socket if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ perror("socket:"); exit(1); } //2. 连接服务器 struct sockaddr_in serviceaddr; memset(&serviceaddr, 0, sizeof(serviceaddr)); serviceaddr.sin_family = AF_INET; serviceaddr.sin_port = htons(atoi(argv[2])); if(inet_pton(AF_INET, argv[2], &serviceaddr.sin_addr.s_addr) < 0){ perror("inet_pton:"); exit(1); } if(connect(socket_fd, (struct sockaddr *)&serviceaddr, sizeof(serviceaddr)) < 0){ perror("connect"); exit(1); } //3. read/write char buff[512]; size_t size; char *s = ">"; while(1){ write(STDOUT_FILENO, s, 1); memset(buff, 0, 1024); size = read(STDIN_FILENO, buff, sizeof(buff)); if(size <0 ) continue; buff[size -1] = '\0'; if(write(socket_fd, buff, sizeof(buff)) < 0){ perror("write"); }else{ if(read(socket_fd, buff, sizeof(buff)) <0){ perror("read"); continue; }else{ printf("%s\n",buff); } } } //关闭套接字 close(socket_fd); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具