0


网络编程 | 多进程多线程并发服务器代码实现

在这里插入图片描述

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。


多进程多线程并发服务器


专栏:《网络编程》


多进程并发服务器

使用多进程并发服务器时要考虑以下几点:

  • 父进程最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符);
  • 系统内创建进程个数(与内存大小相关);
  • 进程创建过多是否降低整体服务性能(进程调度);

server

/* server.c */#include<stdio.h>#include<string.h>#include<netinet/in.h>#include<arpa/inet.h>#include<signal.h>#include<sys/wait.h>#include<sys/types.h>#include"wrap.h"#defineMAXLINE80#defineSERV_PORT800voiddo_sigchild(int num){while(waitpid(0,NULL, WNOHANG)>0);}intmain(void){structsockaddr_in servaddr, cliaddr;socklen_t cliaddr_len;int listenfd, connfd;char buf[MAXLINE];char str[INET_ADDRSTRLEN];int i, n;pid_t pid;structsigaction newact;
    newact.sa_handler = do_sigchild;sigemptyset(&newact.sa_mask);
    newact.sa_flags =0;sigaction(SIGCHLD,&newact,NULL);

    listenfd =Socket(AF_INET, SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
    servaddr.sin_port =htons(SERV_PORT);Bind(listenfd,(structsockaddr*)&servaddr,sizeof(servaddr));Listen(listenfd,20);printf("Accepting connections ...\n");while(1){
        cliaddr_len =sizeof(cliaddr);
        connfd =Accept(listenfd,(structsockaddr*)&cliaddr,&cliaddr_len);

        pid =fork();if(pid ==0){Close(listenfd);while(1){
                n =Read(connfd, buf, MAXLINE);if(n ==0){printf("the other side has been closed.\n");break;}printf("received from %s at PORT %d\n",inet_ntop(AF_INET,&cliaddr.sin_addr, str,sizeof(str)),ntohs(cliaddr.sin_port));for(i =0; i < n; i++)
                    buf[i]=toupper(buf[i]);Write(connfd, buf, n);}Close(connfd);return0;}elseif(pid >0){Close(connfd);}elseperr_exit("fork");}Close(listenfd);return0;}

client

/* client.c */#include<stdio.h>#include<string.h>#include<unistd.h>#include<netinet/in.h>#include"wrap.h"#defineMAXLINE80#defineSERV_PORT6666intmain(int argc,char*argv[]){structsockaddr_in servaddr;char buf[MAXLINE];int sockfd, n;

    sockfd =Socket(AF_INET, SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);
    servaddr.sin_port =htons(SERV_PORT);Connect(sockfd,(structsockaddr*)&servaddr,sizeof(servaddr));while(fgets(buf, MAXLINE,stdin)!=NULL){Write(sockfd, buf,strlen(buf));
        n =Read(sockfd, buf, MAXLINE);if(n ==0){printf("the other side has been closed.\n");break;}elseWrite(STDOUT_FILENO, buf, n);}Close(sockfd);return0;}

多线程并发服务器

在使用线程模型开发服务器时需考虑以下问题:

  • 调整进程内最大文件描述符上限;
  • 线程如有共享数据,考虑线程同步;
  • 服务于客户端线程退出时,退出处理(退出值,分离态);
  • 系统负载,随着链接客户端增加,导致其它线程不能及时得到CPU;

server

/* server.c */#include<stdio.h>#include<string.h>#include<netinet/in.h>#include<arpa/inet.h>#include<pthread.h>#include"wrap.h"#defineMAXLINE80#defineSERV_PORT6666structs_info{structsockaddr_in cliaddr;int connfd;};void*do_work(void*arg){int n,i;structs_info*ts =(structs_info*)arg;char buf[MAXLINE];char str[INET_ADDRSTRLEN];/* 可以在创建线程前设置线程创建属性,设为分离态,哪种效率高内? */pthread_detach(pthread_self());while(1){
        n =Read(ts->connfd, buf, MAXLINE);if(n ==0){printf("the other side has been closed.\n");break;}printf("received from %s at PORT %d\n",inet_ntop(AF_INET,&(*ts).cliaddr.sin_addr, str,sizeof(str)),ntohs((*ts).cliaddr.sin_port));for(i =0; i < n; i++)
            buf[i]=toupper(buf[i]);Write(ts->connfd, buf, n);}Close(ts->connfd);}intmain(void){structsockaddr_in servaddr, cliaddr;socklen_t cliaddr_len;int listenfd, connfd;int i =0;pthread_t tid;structs_info ts[256];

    listenfd =Socket(AF_INET, SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
    servaddr.sin_port =htons(SERV_PORT);Bind(listenfd,(structsockaddr*)&servaddr,sizeof(servaddr));Listen(listenfd,20);printf("Accepting connections ...\n");while(1){
        cliaddr_len =sizeof(cliaddr);
        connfd =Accept(listenfd,(structsockaddr*)&cliaddr,&cliaddr_len);
        ts[i].cliaddr = cliaddr;
        ts[i].connfd = connfd;/* 达到线程最大数时,pthread_create出错处理, 增加服务器稳定性 */pthread_create(&tid,NULL, do_work,(void*)&ts[i]);
        i++;}return0;}

client

/* client.c */#include<stdio.h>#include<string.h>#include<unistd.h>#include<netinet/in.h>#include"wrap.h"#defineMAXLINE80#defineSERV_PORT6666intmain(int argc,char*argv[]){structsockaddr_in servaddr;char buf[MAXLINE];int sockfd, n;

    sockfd =Socket(AF_INET, SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);
    servaddr.sin_port =htons(SERV_PORT);Connect(sockfd,(structsockaddr*)&servaddr,sizeof(servaddr));while(fgets(buf, MAXLINE,stdin)!=NULL){Write(sockfd, buf,strlen(buf));
        n =Read(sockfd, buf, MAXLINE);if(n ==0)printf("the other side has been closed.\n");elseWrite(STDOUT_FILENO, buf, n);}Close(sockfd);return0;}

在这里插入图片描述
在这里插入图片描述



本文转载自: https://blog.csdn.net/qq_43471489/article/details/130514558
版权归原作者 Mindtechnist 所有, 如有侵权,请联系我们删除。

“网络编程 | 多进程多线程并发服务器代码实现”的评论:

还没有评论