下面的程序是创建n个打印进程
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <wait.h>
-
-
- int main(void){
- int t=0;
- while(1){ //循环一次,父进程创建一新进程
-
- pid_t pid=fork(); //从这句后就是主程序创建一新进程,每个线程pid值选择自己执行的代码
- if(pid==0){ //子进程
- while(1){
-
- printf("%d:%d\n",getpid(),t);
- t++;
- sleep(1);
- }
-
- }else{ //父进程
- sleep(5);
- }
- }
- }
在这个程序的基础上就会理解服务器的并行接收客户端的原理了,这种属于批量创建新进程,每个新进程执行相同的代码。
采用多进程的并发服务器
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
-
-
- int main(void){
- struct sockaddr_in serv,*p;
- memset(&serv,0,sizeof(serv));
- p=&serv;
- p->sin_family=AF_INET;
- p->sin_addr.s_addr=htonl(INADDR_ANY);
- p->sin_port=htons(3000);
-
- int sk=socket(PF_INET,SOCK_STREAM,0);
- if(sk==-1){
- puts("socket error\n");
- exit(1);
- }
-
- int opt=1;
- setsockopt(sk,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt)); //服务器地址复用
-
- if(bind(sk,(struct sockaddr*)&serv,sizeof(serv))==-1){
- puts("bind error\n");
- exit(1);
- }
-
- if(listen(sk,10)==-1){
- puts("listen error\n");
- exit(1);
- }
- puts("listening port\n");
- int n=0;
-
- while(n<50){
- pid_t pid=fork(); //父进程创建子进程,新进程数控制50个
- if(pid==0){
- while(1){
- int ck=accept(sk,NULL,NULL);
- if(ck==-1){
- puts("accept error\n");
- exit(1);
- }
- //-----------------------------------------------------------------
- int t=0; //发送一个自增数到客户端
- while(1){
- write(ck,&t,sizeof(t));
- sleep(1); //暂停1秒
- t++;
- }
- }
-
- }else{ //父进程不执行代码,直接跳到accept状态
- n++;
- }
-
-
- }
- while(1){ //父进程产生50个新进程后循环等待,防止主程序退出,中止产生的新进程中止运行
- ;
- }
-
- return 0;
- }
-
-
-
-
-
-
此程序一次产生50个accept新进程,所以可以同时接收50个客户端的接入。此程序未加入新进程的退出机制。
加入子进程退出机制的多进程并发服务器
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <wait.h>
-
-
- int main(void){
- struct sockaddr_in serv,*p;
- memset(&serv,0,sizeof(serv));
- p=&serv;
- p->sin_family=AF_INET;
- p->sin_addr.s_addr=htonl(INADDR_ANY);
- p->sin_port=htons(3000);
-
- int sk=socket(PF_INET,SOCK_STREAM,0);
- if(sk==-1){
- puts("socket error\n");
- exit(1);
- }
-
- int opt=1;
- setsockopt(sk,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt)); //服务器地址复用
-
- if(bind(sk,(struct sockaddr*)&serv,sizeof(serv))==-1){
- puts("bind error\n");
- exit(1);
- }
-
- if(listen(sk,10)==-1){
- puts("listen error\n");
- exit(1);
- }
- puts("listening port\n");
- int stat;
-
- while(1){
- int ck=accept(sk,NULL,NULL); //父进程停留在这里,如连接到客户端,则产生一新子进程
-
- if(ck==-1){
- puts("accept error\n");
- continue;
- }else{
- puts("one client linking...");
- }
-
- pid_t pid=fork();
- if(pid==0){ //子进程开始
-
- int t=0;
- while(t<10){
- write(ck,&t,sizeof(t));
- sleep(1);
- t++;
- }
- close(sk);
- close(ck);
- exit(0); //非常重要,子进程发出停止信号
- }
-
- close(ck); //非常重要,如没有这句,客户端不退出
- waitpid(-1,&stat,WNOHANG); //父进程关闭停止的子进程
- }
-
- return 0;
- }
1此程序accept在fork语句前,所以不会一次生成多个子进程,而是连接一个客户端后才生成一个新进程。