多进程网络服务

多进程网络服务_第1张图片

 

1、高性能网络服务程序

  Linux的一个应用优势是可用于设计各种高性能网络服务程序,高性能的一个特点就是实现并发访问处理,及同时为多个在线用户提供服务;多进程网络服务、多线程网络服务、线程池网络服务;

2、多进程网络服务

  :利用Linux系统中的父子进程关系为多用户提供并发服务,是一种比较流行的并发服务技术,其基本理念是:来一个用户,启动一个服务进程。若有新连接到来,则启动子进程与其交互,服务结束后,其子进程自动退出。

模型如下:

多进程网络服务_第2张图片

3、代码实现:

用一个整数的运算模拟多进程的网络服务。

(1)、utili.h

 

#include#include#include#include#include#include#include#include#define SERVER_PORT  9090#define SERVER_IP    "127.0.0.1"#define LISTEN_QUEUE  5#define BUFFER_SIZE   255typedef enum{ADD,SUB,MUL,DIV,MOD, QUIT}OPER_TYPE;typedef struct OperStruct{
   int op1;
   int op2;
   OPER_TYPE oper;}OperStruct;

(2)、ser.c

 

#include"../utili.h"void Process_Handler(int sockConn);void Process_Handler(int sockConn){
   OperStruct op;
   int result;
   while(1){
       int res = recv(sockConn, &op, sizeof(op), 0);
       if(res == -1){
           printf("recv data fail.\n");
           continue;
       }  
       if(op.oper == ADD){
           result = op.op1 + op.op2;
       }else if(op.oper == SUB)
       {  
           result = op.op1 - op.op2;
       }else if(op.oper == MUL){
           result = op.op1 * op.op2;
       }else if(op.oper == DIV){
           result = op.op1 / op.op2;
       }else if(op.oper == QUIT){
           break;
       }  

       res = send(sockConn, &result, sizeof(result), 0);
       if(res == -1){
           printf("send data fail.\n");
           continue;
       }
   }
   close(sockConn);}int main(void){
   int sockSer = socket(AF_INET, SOCK_STREAM, 0);
   if(sockSer == -1){
       perror("socket");
       return -1;
   }
   struct sockaddr_in addrSer, addrCli;
   addrSer.sin_family = AF_INET;
   addrSer.sin_port = htons(SERVER_PORT);
   addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

   socklen_t len = sizeof(struct sockaddr);
   int res = bind(sockSer, (struct sockaddr*)&addrSer, len);
   if(res == -1){
       perror("bind");
       close(sockSer);
       return -1;      
  }

   listen(sockSer, LISTEN_QUEUE);

   int sockConn;
   while(1){
       printf("Server Wait Client Connect.......\n");
       sockConn = accept(sockSer, (struct sockaddr*)&addrCli, &len);
       if(sockConn == -1){
           printf("Server Accept Client Connect Fail.\n");
           continue;
       }else{
           printf("Server Accept Client Connect Success.\n");
           printf("Client IP:>%s\n", inet_ntoa(addrCli.sin_addr));
           printf("Client Port:>%d\n",ntohs(addrCli.sin_port));
       }

       pid_t pid;
       pid = fork();
       if(pid == 0){
           close(sockSer);
           Process_Handler(sockConn);
           exit(0);
       }else if(pid > 0){
           close(sockConn);
           continue;    
       }else{
           printf("Create Process Fail.\n");
           continue;
       }
   }
   close(sockSer);
   return 0;}

(3)、cli.c

 

#include"utili.h"void InputData(OperStruct *pt);void InputData(OperStruct *pt){
   printf("please input op1 and op2 : ");
   scanf("%d %d", &(pt->op1), &(pt->op2));}//Cliint main(void){
   int sockCli = socket(AF_INET, SOCK_STREAM, 0);
   if(sockCli == -1){
       perror("socket");
       return -1;
   }  
   struct sockaddr_in addrSer;
   addrSer.sin_family = AF_INET;
   addrSer.sin_port = htons(SERVER_PORT);
   addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

   socklen_t len = sizeof(struct sockaddr);
   int res = connect(sockCli, (struct sockaddr*)&addrSer, len);
   if(res == -1){
       perror("connect");
       close(sockCli);
       return -1;
   }else{
       printf("Client Connect Server Success.\n");
   }

   char cmd[2];
   OperStruct  op;
   int result;
   while(1){
       printf("Please input operator : ");
       scanf("%s",cmd);
       if(strcmp(cmd, "+") == 0){
           op.oper = ADD;
           InputData(&op);
       }else if(strcmp(cmd,"-") == 0){
           op.oper = SUB;
           InputData(&op);
       }else if(strcmp(cmd,"*") == 0){
           op.oper = MUL;
           InputData(&op);
       }else if(strcmp(cmd,"/") == 0){
           op.oper = DIV;
           InputData(&op);
       }else if(strcmp(cmd, "quit") == 0){
           op.oper = QUIT;
       }else{    
           printf("Cmd invalid.\n");
       }

       res = send(sockCli, &op, sizeof(op), 0);
       if(res == -1){
           printf("send data fail.\n");
           continue;
       }
       if(op.oper == QUIT)
           break;
       res = recv(sockCli, &result, sizeof(result), 0);
       if(res == -1){
           printf("recv data fail.\n");
           continue;
       }
       printf("result = %d\n", result);
   }
   close(sockCli);
   return 0;}

运行结果:

服务器端

多进程网络服务_第3张图片客户1

客户1

多进程网络服务_第4张图片

客户2

多进程网络服务_第5张图片

4、结果分析

  (1)、utili.h在ser.c的上一层目录,utili.h和cli.c是在同一层目录;

  (2)、进程服务器:socker是引用计数器模型,close()是减少一个,并没有真正的关闭,每次创建一个进程都会给socker引用计数器加1;

  (3)、缺点:a、启动和关闭子进程带来很大的开销;b、系统最多只能产生512个进程,也就是说最多只有512个客户,形成不了处理大型访问的情形;

 

喜欢本文的朋友们,欢迎长按下图关注订阅号编程小兔崽,收看更多精彩内容

多进程网络服务_第6张图片

每天进步一点点,如果有用给小编点个赞

想了解更多文章可以观看-Socket网络编程

想了解更多文章请观看-线程高级操作

想了解更多文章请观看-Linux多线程编程

想了解更多文章请观看-线程

你可能感兴趣的:(Linux,C/C++)