多进程服务端
-
利用信号回收子进程例子(利用子进程结束后向父进程发送SIGCHLD信号来回收子进程
#include <me.h> //子进程结束信号 void read_childproc(int signo) { int status; pid_t id = waitpid(-1,&status,WNOHANG); if (WIFEXITED(status)) { printf("Removed proc id: %d \n",id); printf("Child send: %d \n",WEXITSTATUS(status)); } } int main(int argc,char *argv[]) { pid_t pid; struct sigaction act; act.sa_handler = read_childproc; sigemptyset(&act.sa_mask);//信号处理函数执行时期的信号屏蔽字 act.sa_flags = 0; sigaction(SIGCHLD,&act,0); pid = fork(); if (pid == 0) { puts("Hi! I'm child process."); sleep(10); return 12; } else { printf("Child proc id: %d \n",pid); pid = fork(); if (pid == 0)//第二个子进程 { puts("Hi! I'm child process"); sleep(10); exit(24); } else//主进程 { int i; printf("Child proc id: %d \n",pid); for (i=0; i<5; i++) { puts("wait..."); sleep(5); } } } return 0; }
-
通过多个进程来实现并发(
由父进程来监听连接请求,多个子进程来处理逻辑 ,因为fork后文件描述符也被复制一份到子进程,因为一个端口对应一个套接字,而此时文件描述符多了1份,
-
让唯一的父进程处理连接请求,那么去掉fork前连接成功的客户端socket fd,
-
多个子进程只需要负责数据,不需要监听,那么关闭监听的socket fd
#include <me.h> #define BUF_SIZE 30 void read_childproc(int); int main(int argc,char *argv[]) { int serv_sock,clnt_sock; struct sockaddr_in serv_adr,clnt_adr; pid_t pid; struct sigaction act; int str_len,state; socklen_t adr_sz; char buf[BUF_SIZE]; if (argc != 2) { printf("Usage : %s <port> \n",argv[0]); exit(1); } //注册信号处理函数 act.sa_handler = read_childproc; sigemptyset(&act.sa_mask); act.sa_flags = 0; state = sigaction(SIGCHLD,&act,0); if (state == -1) error_handle("sigaction error") serv_sock = socket(AF_INET,SOCK_STREAM,0); memset(&serv_adr,0,sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(atoi(argv[1])); if (bind(serv_sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr)) == -1) error_handle("bind() error") if (listen(serv_sock,5) == -1) error_handle("listen() error") while(1) { adr_sz = sizeof(clnt_adr); clnt_sock = accept(serv_sock,(struct sockaddr*)&clnt_adr,&adr_sz); if (clnt_sock == -1) continue; else puts("new client connected..."); pid = fork(); if (pid == -1)//连接成功,但是fork失败 { close(clnt_sock); continue; } if (pid == 0) { close(serv_sock); //子进程不需要监听相应端口,所以此进程关闭该复制的套接字 while((str_len = read(clnt_sock,buf,BUF_SIZE)) != 0) write(clnt_sock,buf,str_len); close(clnt_sock); puts("client disconnected..."); return 0; } else { //父进程用不到此套接字(因为已经交给子进程来处理了) close(clnt_sock); } } close(serv_sock);//父进程结束,服务器端套接字关闭 return 0; } void read_childproc(int signo) { pid_t pid; int status; pid = waitpid(-1,&status,WNOHANG);//不阻塞回收子进程 printf("removed proc id: %d \n",pid); }
-
-
分割IO程序,开子进程让2个进程分别In和out
普通回声服务器客户端(写了之后在读:
#include <me.h> #define BUF_SIZE 1024 int main(int argc,char *argv[]) { int sock; char message[BUF_SIZE]; int str_len; struct sockaddr_in serv_adr; if (argc != 3) { printf("Usage : %s <IP> <port>\n",argv[0]); exit(1); } sock = socket(AF_INET,SOCK_STREAM,0); if (sock == -1) error_handle("socket() error"); memset(&serv_adr,0,sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = inet_addr(argv[1]); serv_adr.sin_port = htons(atoi(argv[2])); if (connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr)) == -1) error_handle("connect() error") else puts("connected..."); //已经连接上了服务器 while(1) { fputs("Input message(Q to quit): ",stdout); fgets(message,BUF_SIZE,stdin); if (!strcmp(message,"q\n") || !strcmp(message,"Q\n")) break; write(sock,message,strlen(message)); str_len = read(sock,message,BUF_SIZE-1); message[str_len] = 0; printf("Message from server: %s",message); } close(sock); return 0; }
开子进程同时读和写:
#include <me.h> #define BUF_SIZE 30 void read_routine(int,char*); void write_routine(int,char*); int main(int argc,char *argv[]) { int sock; pid_t pid; char buf[BUF_SIZE]; struct sockaddr_in serv_adr; if (argc != 3) { printf("Usage : %s <IP> <port> \n",argv[0]); exit(1); } sock = socket(AF_INET,SOCK_STREAM,0); memset(&serv_adr,0,sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = inet_addr(argv[1]); serv_adr.sin_port = htons(atoi(argv[2])); if (connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr)) == -1) error_handle("connect() error"); //IO分割 pid = fork(); if (pid == 0) { write_routine(sock,buf); } else { read_routine(sock,buf); } close(sock); return 0; } void read_routine(int sock,char *buf) { while(1) { int str_len = read(sock,buf,BUF_SIZE); if (str_len == 0) return ; buf[str_len] = 0; printf("Message from server: %s",buf); } } void write_routine(int sock,char *buf) { while(1) { fgets(buf,BUF_SIZE,stdin); if (!strcmp(buf,"q\n") || !strcmp(buf,"Q\n")) { shutdown(sock,SHUT_WR); return ; } write(sock,buf,strlen(buf)); } }
来自<<TCP/IP 网络编程 尹圣雨>>