600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 128-网络编程:TCP通信的并发(多进程实现并发服务器)

128-网络编程:TCP通信的并发(多进程实现并发服务器)

时间:2019-12-19 08:47:13

相关推荐

128-网络编程:TCP通信的并发(多进程实现并发服务器)

3、TCP通信的并发(多进程实现并发服务器)

3.1 多进程实现并发服务器

要实现TCP通信服务器处理并发任务,使用多线程或者多进程来解决。思路:1. 一个父进程,多个子进程2. 父进程负责等待并接受客户端连接3. 子进程: 完成通信,接受一个客户端连接,就创建一个子进程用于通信。

#include <stdio.h>#include <arpa/inet.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <wait.h>#include <errno.h>void recyleChild(int arg) {while(1) {int ret = waitpid(-1, NULL, WNOHANG);if(ret == -1) {// 所有的子进程都回收了break;}else if(ret == 0) {// 还有子进程活着break;} else if(ret > 0){// 被回收了printf("子进程 %d 被回收了\n", ret);}}}int main() {struct sigaction act;act.sa_flags = 0;sigemptyset(&act.sa_mask);act.sa_handler = recyleChild;// 注册信号捕捉sigaction(SIGCHLD, &act, NULL);// 创建socketint lfd = socket(PF_INET, SOCK_STREAM, 0);if(lfd == -1){perror("socket");exit(-1);}struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY;// 绑定int ret = bind(lfd,(struct sockaddr *)&saddr, sizeof(saddr));if(ret == -1) {perror("bind");exit(-1);}// 监听ret = listen(lfd, 128);if(ret == -1) {perror("listen");exit(-1);}// 不断循环等待客户端连接while(1) {struct sockaddr_in cliaddr;int len = sizeof(cliaddr);// 接受连接int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &len);if(cfd == -1) {//系统调用被信号打断,在调用系统调用时,可能会接收到某个信号而导致调用退出//解决办法: 直接跳过,执行下一次循环即可if(errno == EINTR) {continue;}perror("accept");exit(-1);}// 每一个连接进来,创建一个子进程跟客户端通信pid_t pid = fork();if(pid == 0) {// 子进程// 获取客户端的 ip和端口号 信息char cliIp[16];inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, cliIp, sizeof(cliIp));unsigned short cliPort = ntohs(cliaddr.sin_port);printf("client ip is : %s, prot is %d\n", cliIp, cliPort);// 接收客户端发来的数据char recvBuf[1024];while(1) {int len = read(cfd, &recvBuf, sizeof(recvBuf));if(len == -1) {perror("read");exit(-1);}else if(len > 0) {printf("recv client : %s\n", recvBuf);} else if(len == 0) {printf("client closed....\n");break;/如果客户端断开,直接跳出这个while循环}//再将读到数据发送给客户端write(cfd, recvBuf, strlen(recvBuf) + 1);}close(cfd);exit(0); // 退出当前子进程}}close(lfd);return 0;}

// TCP通信的客户端#include <stdio.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>#include <stdlib.h>int main() {// 1.创建套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd == -1) {perror("socket");exit(-1);}// 2.连接服务器端struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;inet_pton(AF_INET, "192.168.193.128", &serveraddr.sin_addr.s_addr);serveraddr.sin_port = htons(9999);int ret = connect(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));if(ret == -1) {perror("connect");exit(-1);}// 3. 通信char recvBuf[1024];int i = 0;while(1) {sprintf(recvBuf, "data : %d\n", i++);// 给服务器端发送数据write(fd, recvBuf, strlen(recvBuf)+1);int len = read(fd, recvBuf, sizeof(recvBuf));if(len == -1) {perror("read");exit(-1);} else if(len > 0) {printf("recv server : %s\n", recvBuf);} else if(len == 0) {// 表示服务器端断开连接printf("server closed...");break;//如果服务端断开,直接跳出这个while循环}sleep(1);}// 关闭连接close(fd);return 0;}

程序小bug:

将客户端ctrl+c关掉,在服务端会出现这个错误:

为什么会出现这样的问题:按理来说,应该是打印 “client closed”:

原因:文件描述没有关闭,会出现一些问题。

解决方法:

如果客户端断开,直接break跳出循环;

// 接收客户端发来的数据char recvBuf[1024];while(1) {int len = read(cfd, &recvBuf, sizeof(recvBuf));if(len == -1) {perror("read");exit(-1);}else if(len > 0) {printf("recv client : %s\n", recvBuf);} else if(len == 0) {printf("client closed....\n");break;/如果客户端断开,直接跳出这个while循环}//再将读到数据发送给客户端write(cfd, recvBuf, strlen(recvBuf) + 1);}close(cfd);exit(0); // 退出当前子进程}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。