1、高性能网络服务程序
Linux的一个应用优势是可用于设计各种高性能网络服务程序,高性能的一个特点就是实现并发访问处理,及同时为多个在线用户提供服务;多进程网络服务、多线程网络服务、线程池网络服务;
2、多进程网络服务
:利用Linux系统中的父子进程关系为多用户提供并发服务,是一种比较流行的并发服务技术,其基本理念是:来一个用户,启动一个服务进程。若有新连接到来,则启动子进程与其交互,服务结束后,其子进程自动退出。
模型如下:
3、代码实现:
用一个整数的运算模拟多进程的网络服务。
(1)、utili.h
#include<unistd.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<pthread.h> #define SERVER_PORT 9090 #define SERVER_IP "127.0.0.1" #define LISTEN_QUEUE 5 #define BUFFER_SIZE 255 typedef 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)); } //Cli int 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; }
运行结果:
服务器端
客户1
客户1
客户2
4、结果分析
(1)、utili.h在ser.c的上一层目录,utili.h和cli.c是在同一层目录;
(2)、进程服务器:socker是引用计数器模型,close()是减少一个,并没有真正的关闭,每次创建一个进程都会给socker引用计数器加1;
(3)、缺点:a、启动和关闭子进程带来很大的开销;b、系统最多只能产生512个进程,也就是说最多只有512个客户,形成不了处理大型访问的情形;
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。