Linux网络编程多进程模型

来源:互联网 发布:知乎粉丝排名 编辑:程序博客网 时间:2024/06/03 16:04
#include <string.h>#include <errno.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#include <stdlib.h>#include <stdio.h>#define SERV_PORT 8080#define MAXLINE 100#define MAXSIZE 4096void sys_error(const char *fun_str,int exitno){perror(fun_str);exit(exitno);}void sig_handle(int signo){int status;pid_t pid;while( (pid = waitpid(-1,&status,WNOHANG))>0 ){printf("child %d terminated\n",pid);}return;}//使用多进程版本中容易忽视的问题 ,我们只是负责创建了子进程去处理去客户端的交互 ,却没有考虑到子进程结束时 ,父进程并没有回收子进程的资源//子进程在结束时会发送SIGCHLD信号 因此我们可以在信号处理函数中 去回收子进程的资源(PCB等)int main(void){int ret=0;int n;int sockfd,connfd;int cli_len;struct sockaddr_in serv_addr,cli_addr;char buf[MAXLINE];char info[MAXSIZE];pid_t pid;sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){sys_error("socket",-1);}bzero(&serv_addr,sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);ret = bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));if(-1 == ret){sys_error("bind",-2);}//listen 中backlog的值为两个连接队列的和 已完成连接队列 和正处于三次握手的待连接队列ret = listen(sockfd,20);if(-1 == ret){sys_error("listen",-3);}printf("waiting for connnect\n");//SIGCHLD的信号处理函数用于回收子进程的资源signal(SIGCHLD,sig_handle);while(1){cli_len = sizeof(cli_addr);connfd =accept(sockfd,(struct sockaddr*)&cli_addr,&cli_len);if(-1 == connfd){if(EINTR == errno){connfd = accept(sockfd,(struct sockaddr*)&cli_addr,&cli_len);}sys_error("accept",-4);}printf("recived from ip %s port %d\n",inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr,buf,sizeof(buf)),ntohs(cli_addr.sin_port));/*accept阻塞于等待客户端的连接 如果此时服务端需要读取数据又会阻塞 这时服务端便不能与新的客户端进行连接 如果将read设置为非阻塞模式,也只是以轮询的模式与新的客户端进行连接 如果服务端有数据需要读取 这时新的连接又会失败这时采取多进程的方式处理 父进程等待客户端的连接 而子进程负责处理与客户端具体的交互*/pid = fork();if(0==pid){//创建父子进程时 子进程是父进程的完全拷贝 关闭不必要的文件描述符close(sockfd);while(1){n = read(connfd, info, sizeof(info));if(n<0){sys_error("read",-6);}ret = write(connfd, info, n); if(ret<0){sys_error("write",-7);}}ret = close(connfd);if(-1 == ret){sys_error("close",-5);}}else if(pid >0){//父进程只负责监听来自客户端的连接close(connfd);}else{sys_error("fork",-8);}}return 0;}

原创粉丝点击