使用select函数提高服务器的处理能力——服务器端代码

#include <sys/types.h>
#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值