使用select函數提高服務器的處理能力——服務器端代碼

#include
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>

#include <fcntl.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/select.h>
#define DEFAULT_PORT 6666

int main(int argc, char** argv)
{
    //監聽socket: serverfd. 數據傳輸socket: acceptfd
    int serverfd, acceptfd;
    struct sockaddr_in my_addr;
    struct sockaddr_in their_addr;
    unsigned int sin_size;
    unsigned int myport=6666,lisnum=10;

    if((serverfd=socket(AF_INET, SOCK_STREAM, 0))== -1)
    {
        perror("create socket failed!");
        return -1;
    }
    printf("socket ok!\n");
    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(DEFAULT_PORT);
    my_addr.sin_addr.s_addr=INADDR_ANY;
    bzero(&(my_addr.sin_zero),0);
    if(bind(serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))==-1)
    {
        perror("bind failed!");
        return -2;
    }
    printf("bind ok!\n");

    if(listen(serverfd, lisnum)==-1)
    {
        perror("listen failed!");
        return -3;
    }
    printf("listen ok!\n");

    fd_set client_fdset;    //監聽文件描述符集合
    int maxsock;            //監聽fd中最大的文件號
    struct timeval tv;      //超時返回時間
    int client_sockfd[5];   //存放活動的sockfd
    
    bzero((void*)client_sockfd, sizeof(client_sockfd));
    
    int conn_amount=0;      //用來記錄描述符數量
    maxsock=serverfd;
    char buffer[1024];
    int ret=0;
    while(1)
    {
        FD_ZERO(&client_fdset);     //將文件描述符集合清零
        FD_SET(serverfd, &client_fdset);        //加入服務器描述符
        //設置超時時間
        tv.tv_sec=30;
        tv.tv_usec=0;
        
        //把活動的fd加入到文件描述符中
        for(int i=0;i<5;i++)
        {
            //listen的參數設爲5,所以i<5
            if(client_sockfd[i]!=0)
                FD_SET(client_sockfd[i], &client_fdset);
        }

        //select函數
        ret=select(maxsock+1, &client_fdset, NULL, NULL, &tv);
        if(ret<0)
        {
            perror("select error!\n");
            break;
        }
        else if(ret==0)
        {
            
            perror("timeout!\n");
            continue;
        }

        //輪詢各個fd
        for(int i=0;i<conn_amount; i++)
        {
            //
               //判斷終端的fd是否在可讀描述符集合中
               if(FD_ISSET(client_sockfd[i],&client_fdset))
               {
                    
                    printf("start recv from client[%d]:\n",i);
                    //接收客戶端套接字的數據
                    ret=recv(client_sockfd[i],buffer, 1024,0);
                    
                    if(ret<=0)
                    {
                        printf("client[%d] close\n",i);
                        close(client_sockfd[i]);
                        //將fd從客戶端fd集合中刪除
                        FD_CLR(client_sockfd[i], &client_fdset);
                        client_sockfd[i]=0;
                    }
                    else
                        printf("recv from client[%d] : %s\n",i,buffer);
                                                                                                                      }
        }
        
        //檢查是否有新的鏈接,如果有,則接受,加入到client_sockfd中
        if(FD_ISSET(serverfd,&client_fdset))
        {
            //接受鏈接
            struct sockaddr_in client_addr;
            size_t size=sizeof(struct sockaddr_in);
            int sock_client=accept(serverfd, (struct sockaddr *)&client_addr, (unsigned int*)(&size));
            if(sock_client<0)
            {
                perror("accept error!\n");
                continue;
            }
        

        //把鏈接加入到fd集合中
        if(conn_amount<5)
        {
            client_sockfd[conn_amount++]=sock_client;
            bzero(buffer, 1024);
            strcpy(buffer, "this is server! welcomne!\n");
            send(sock_client,buffer, 1024,0);
            printf("new connection client[%d] %s:%d\n", conn_amount, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
            bzero(buffer, sizeof(buffer));
            
            ret=recv(sock_client, buffer, 1024,0);
            if(ret<0)
            {
            
                perror("recv error!\n");
                close(serverfd);
                return -1;
            }
            printf("recv : %s\n",buffer);
            if(sock_client>maxsock)
                maxsock=sock_client;
            else
            {
                printf("amx connections!!! quit!\n");
                break;
            }
            }
        }
    }
    for(int i=0;i<5;i++)
    {
        if(client_sockfd[i]!=0)
            close(client_sockfd[i]);
    }
    close(serverfd);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章