多路IO转接 select模型

select函数就一socket文件描述符监测函数,可以监测读和写。没有read和write时候将阻塞在那儿,相比于多进程和多线程处理,它更加节省资源。废话不多说 上demo

#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#define TCP_PORT 9999
#define SOCK_NUM 1024
int main()
{
    fd_set allset,rest;
    int socket_ser,socket_accept;
    int socketfd[SOCK_NUM];
    struct sockaddr_in addr,addr_c;
    int maxfd;
    char recfub[1500];
    socket_ser = socket(AF_INET,SOCK_STREAM,0);
    bzero(&addr,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(TCP_PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(socket_ser,(struct sockaddr *)&addr,sizeof(addr));
    listen(socket_ser,128);
    //首先监听socket_ser
    FD_ZERO(&allset);
    FD_SET(socket_ser,&allset);
    memset(socketfd,-1, sizeof(socketfd));
    maxfd = socket_ser;

    while (1)
    {
        rest = allset;
        //监听maxfd+1个文件描叙符的读
        int num = select(maxfd+1,&rest,NULL,NULL,NULL);
        if(num<0)
        {
            printf("服务器挂了\n");
        }
        //select的返回只有有读入的文件描述符是1
        if(FD_ISSET(socket_ser,&rest))
        {
            int i;
            for ( i = 0; i < SOCK_NUM; ++i) {
                if (socketfd[i] == -1)
                    break;
            }
            if (SOCK_NUM == i)
            {
                printf("满了,挂了\n");
                exit(1);
            }
            //保存新的socket
            bzero(&addr_c,sizeof(addr_c));
            int len = sizeof(addr_c);
            socketfd[i] = accept(socket_ser,(struct sockaddr*)&addr_c,(socklen_t *)&len);
            //加入到select监控
            FD_SET(socketfd[i],&allset);
            //更新下监测的文件描述符序号
            if(socketfd[i]>maxfd)
            {
                maxfd = socketfd[i];
            }
            char recip[16];
            printf("Ip is %s,Port is %d\n",inet_ntop(AF_INET,&addr_c.sin_addr,recip,ntohs(addr_c.sin_port)));
            num--;
        }
        if(num>0)
        {
            while(num)
            {
                for (int i = 0; i <SOCK_NUM ; ++i) {
                    if(socketfd[i]>0 && FD_ISSET(socketfd[i],&rest))
                    {
                        bzero(&recfub,sizeof(recfub));
                        int n=0;
                        if (0 == (n=read(socketfd[i],recfub,sizeof(recfub))))
                        {
                            FD_CLR(socketfd[i],&allset);
                            printf("socket: %d关闭连接\n", socketfd[i]);
                            close(socketfd[i]);
                            if (socketfd[i] >= maxfd)
                            {
                                maxfd --;
                            }
                            socketfd[i]=-1;
                            break;
                        } else
                        {
                            printf("%s\n",recfub);
                            write(socketfd[i],recfub,strlen(recfub));

                        }
                    }
                    num --;
                    break;
                    //处理完一个文件描述符继续下一个
                }
            }
        }
    }
    close(socket_ser);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/woshichaoren1/article/details/85533574