• 高性能网络编程



         IO复用使得程序可以同一时候监听多个文件描写叙述符,比方client须要同一时候处理用户输入和网络连接,server端须要同一时候处理监听套接字和连接套接字,select系统调用可以使得我们监听自己感兴趣描写叙述符。可读,可写,异常等事件。select能处理的异常仅仅有带外数据。能同一时候处理描写叙述符的数量受限于FD_SETSIZE的大小(一般1024)。以下这个程序展示了它的一般使用方法。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <libgen.h> //basename
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <assert.h>
    #include <errno.h>
    
    
    int main(int argc, char *argv[]){
        int i, maxi;
        char buf[1024];
        fd_set read_fds, all_read_fds;
        fd_set exception_fds, all_exception_fds;
        int nready, connectfd[FD_SETSIZE];  
        int connfd,sockfd,maxfd;
        
        struct sockaddr_in client_address;
        socklen_t client_addrlen = sizeof(client_address);
        
        if(argc <= 2){ 
            printf("usage: %s ip_address port_number
    ", basename(argv[0]));
            return 1;
        }   
    
        const char *ip = argv[1];
        int port = atoi(argv[2]);
        
        int ret = 0;
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        inet_pton(AF_INET, ip, &address.sin_addr);
        address.sin_port = htons(port);
    
        int listenfd = socket(AF_INET, SOCK_STREAM, 0);
        assert(listenfd >= 0);
        ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
        assert(ret != -1);
        ret = listen(listenfd, 5);
        assert(ret != -1);
    
        maxfd = listenfd;
        maxi = -1;
        for(i= 0; i < FD_SETSIZE; i++)
            connectfd[i] = -1;
        FD_ZERO(&all_read_fds);
        FD_ZERO(&all_exception_fds);
        FD_SET(listenfd, &all_read_fds);
        //do not care about the OOB of listen socket
    
        while(1){
            read_fds = all_read_fds;
            exception_fds = all_exception_fds;
            memset(buf, 0, sizeof(buf));
            nready = select(maxfd + 1, &read_fds, NULL, &exception_fds, NULL);
            //new client connection coming
            if(FD_ISSET(listenfd, &read_fds)){
                connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlen);
                if(connfd < 0){
                    perror("accept failed
    ");
                    exit(-1);
                }
    
                for(i=0; i < FD_SETSIZE; i++)
                    if(connectfd[i] < 0){
                        connectfd[i] = connfd;
                        break;
                    }
                if( i == FD_SETSIZE){
                    printf("too many clients..
    ");
                    exit(-1);
                }
                // add new descriptor to the read set and exception set
                FD_SET(connfd, &all_read_fds);
                FD_SET(connfd, &all_exception_fds);
                if(connfd > maxfd)
                    maxfd = connfd;
                if(i > maxi)
                    maxi = i;// update the max index in connectfd[]
                //we complete the listen socktet processing
                if(--nready <= 0)
                    continue;
            }
            for(i = 0; i <= maxi; i++){
                //check all the connected clients for data
                if((sockfd = connectfd[i]) < 0)
                    continue;
                if(FD_ISSET(sockfd, &read_fds)){
                    ret = recv(sockfd, buf, sizeof(buf) - 1, 0);
                    if(ret <= 0)
                        break;//connection closed
                    // process logic
                    printf("get %d bytes of normal data:%s
    ", ret, buf);
                //we complete the listen socktet processing
                if(--nready <= 0)
                    continue;
            }
            for(i = 0; i <= maxi; i++){
                //check all the connected clients for data
                if((sockfd = connectfd[i]) < 0)
                    continue;
                if(FD_ISSET(sockfd, &read_fds)){
                    ret = recv(sockfd, buf, sizeof(buf) - 1, 0);
                    if(ret <= 0)
                        break;//connection closed
                    // process logic
                    printf("get %d bytes of normal data:%s
    ", ret, buf);
                }else if(FD_ISSET(sockfd, &exception_fds)){
                    //handle exceptions
                    //get out of band data 
                    ret = recv(connfd, buf, sizeof(buf) - 1, MSG_OOB);
                    if(ret <= 0)
                        break;
                    printf("get %d bytes of OOB data: %s", ret, buf);
    
                }
                FD_CLR(sockfd, &all_read_fds);
                FD_CLR(sockfd, &all_exception_fds);
                //after we deal with this client
                close(sockfd);
                if(--nready <= 0)
                    break;
            }
        }
    
        close(listenfd);
        return 0;
    }



    參考:《高性能server编程》和《UNP》


  • 相关阅读:
    A1023 Have Fun with Numbers (20分)(大整数四则运算)
    A1096 Consecutive Factors (20分)(质数分解)
    A1078 Hashing (25分)(哈希表、平方探测法)
    A1015 Reversible Primes (20分)(素数判断,进制转换)
    A1081 Rational Sum (20分)
    A1088 Rational Arithmetic (20分)
    A1049 Counting Ones (30分)
    A1008 Elevator (20分)
    A1059 Prime Factors (25分)
    A1155 Heap Paths (30分)
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/6938137.html
Copyright © 2020-2023  润新知