zoukankan      html  css  js  c++  java
  • linux学习之多高并发服务器篇(一)

    高并发服务器

    高并发服务器

    并发服务器开发

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

    • 父最大文件描述个数(父进程中需要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"
    #define MAXLINE 80
    #define SERV_PORT 8000
    
    
    void do_sigchild(int num)
    {
        waitpid(0, NULL, WNOHANG);
    }
    int main(void)
    {
        struct sockaddr_in servaddr, cliaddr;
        socklen_t cliaddr_len;
        int listenfd, connfd;
        char buf[MAXLINE];
        char str[INET_ADDRSTRLEN];
        int i, n;
        pid_t pid;
        struct sigaction 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, (struct sockaddr *)&servaddr, sizeof(servaddr));
        Listen(listenfd, 20);
        printf("Accepting connections ...
    ");
        while (1) {
            cliaddr_len = sizeof(cliaddr);
            connfd = Accept(listenfd, (struct sockaddr *)&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.
    ");
                        break;
                    }
                    printf("received from %s at PORT %d
    ",
                        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);//若不关长期以往会导致文见文件描述符关闭
                return 0;
            }
            else if (pid > 0) {
                Close(connfd);
            }
            else
                perr_exit("fork");
        }
    }

    client

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include "wrap.h"
    #define MAXLINE 80
    #define SERV_PORT 8000
    int main(int argc, char *argv[])
    {
        struct sockaddr_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, (struct sockaddr *)&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.
    ");
            else
                Write(STDOUT_FILENO, buf, n);
        }
        Close(sockfd);
        return 0;
    }

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

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

    多线程

     server

    /* server.c */
    #include <stdio.h>
    #include <string.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <pthread.h>
    #include "wrap.h"
    #define MAXLINE 80
    #define SERV_PORT 8000
    struct s_info {
        struct sockaddr_in cliaddr;
        int connfd;
    };
    void *do_work(void *arg)
    {
        int n, i;
        struct s_info *ts = (struct s_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.
    ");
                break;
            }
            printf("received from %s at PORT %d
    ",
                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);
    }
    int main(void)
    {
        struct sockaddr_in servaddr, cliaddr;
        socklen_t cliaddr_len;
        int listenfd, connfd;
        int i = 0;
        pthread_t tid;
        struct s_info ts[383];
        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, (struct sockaddr *)&servaddr, sizeof(servaddr));
        Listen(listenfd, 20);
        printf("Accepting connections ...
    ");
        while (1) {
            cliaddr_len = sizeof(cliaddr);
            connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
            ts[i].cliaddr = cliaddr;
            ts[i].connfd = connfd;
            /* 达到线程最大数时,pthread_create出错处理, 增加服务器稳定性 */
            pthread_create(&tid, NULL, do_work, (void*)&ts[i]);
            i++;
        }
        return 0;
    }

    client

    /* client.c */
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include "wrap.h"
    #define MAXLINE 80
    #define SERV_PORT 8000
    int main(int argc, char *argv[])
    {
        struct sockaddr_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, (struct sockaddr *)&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.
    ");
            else
                Write(STDOUT_FILENO, buf, n);
        }
        Close(sockfd);
        return 0;
    }
  • 相关阅读:
    10.12在主函数中输入10个等长的字符串。用另一个函数对它们排序,然后在主函数输出这10个已排好序的字符串。
    10.10 将一个5×5的矩阵中最大的元素放在中心,4个角分别放在4个最小的元素(按从左到右,从上到下的顺序,依次从小到大存放),写一个函数实现之,并用main函数调用。
    10.9 写一个函数,将一个3*3的整型矩阵转置。
    10.8输入一行文字,找出其中大写字母、小写字母、空格、数字及其他字符各有多少?
    10.4 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数,见图。写一函数:实现以上功能,在主函数中输入n个数和输出调整后的n个数。
    10.5 有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。
    10.3 输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。写三个函数;①输入10个数;②进行处理;③输出10个数。
    PHP中文无乱码写法
    教你怎样搜索下载百度网盘、华为网盘、迅雷快传的资源
    Yii框架的安装
  • 原文地址:https://www.cnblogs.com/rainbow1122/p/7875702.html
Copyright © 2011-2022 走看看