• IO多路复用


    服务器:

    #include

    #define IP "192.168.124.73"
    #define PORT 8888

    int deal_CliconnectEvent(int sfd,struct sockaddr_in* saveCin,fd_set* preadfds,int* pmaxfd);
    int deal_keyboradEvent(fd_set readfds,struct sockaddr_in psaveCin[]);
    int deal_CliTackEvent(int newfd,struct sockaddr_in saveCin[],fd_set* preadfds,int* pmaxfd);
    int main(int argc, const char *argv[])
    {
        //创建流式套接字
        int sfd = socket(AF_INET,SOCK_STREAM,0);
        if(sfd < 0){
            fprintf(stderr,"line=%d",__LINE__);
            perror("socket");
            return -1;
        }
        printf("创建流式套接字成功 sfd=%d __%d__\n",sfd,__LINE__);
        //允许端口号被重复使用
        int reuse = 1;
        if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0){
            fprintf(stderr,"line=%d",__LINE__);
            perror("setsockopt");
            return -1;    
        }
        
        //填充服务器的地址信息结构体,真实的地址信息结构体根据地址族制定
        //AF_INET -->man 7 ip
        struct sockaddr_in sin;
        sin.sin_family = AF_INET;
        sin.sin_port   = htons(PORT);
        sin.sin_addr.s_addr = inet_addr(IP);
        //绑定服务器自身的地址信息
        if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0){
            fprintf(stderr,"line:%d",__LINE__);
            perror("bind");
            return -1;
        }
        printf("bind success __%d__\n",__LINE__);
        //套接字设置为被动监听
        if(listen(sfd,128) < 0 ){
            fprintf(stderr,"line:%d",__LINE__);
            perror("listen");
            return -1;    
        }
        printf("listen success __%d__\n",__LINE__);
        //获取链接成功的套接字
        struct sockaddr_in cin;  //存储客户端信息
        socklen_t addrlen = sizeof(cin);
        //会从已经完成链接队列的对头获取一个客户端的信息,生成一个新的文件描述符
        //accept(sfd,NULL,NULL)

        //创建一个读集合 清空readfds

        fd_set readfds,tempfds;
        FD_ZERO(&readfds);
        
        //要检测的文件描述符加入到读集合中
        int maxfd  = sfd;
        FD_SET(0,&readfds);
        FD_SET(sfd,&readfds);
        
        int newfd = -1;

        int s_res;
        char buf[128];
        struct sockaddr_in saveCin[1024-3];
        ssize_t res;
        while(1){
            tempfds = readfds;
            s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
            if(s_res < 0){    
                fprintf(stderr,"line:%d",__LINE__);
                perror("recv");
                return -1;
            }
            else if(s_res == 0){
                printf("time out __%d__\n",__LINE__);
                break;
            }

            for(int i=0;i<=maxfd;i++){
                newfd = i;
                if(FD_ISSET(newfd,&tempfds) == 0)
                    continue;

                if(newfd == 0){
                    printf("键盘");
                    deal_keyboradEvent(readfds,saveCin);
                }
                else if(newfd == sfd){
                    printf("客户端事件\n");
                    deal_CliconnectEvent(sfd,saveCin,&readfds,&maxfd);    
                }
                else{
                    printf("触发客户端交互事件\n");
                    deal_CliTackEvent(newfd,saveCin,&readfds,&maxfd);
                }            

            }    

        }    

        
        //关闭文件描述符    
        close(sfd);
        return 0;
    }

    /*
     * function:    处理客户端连接事件
     * @param [ in] 
     * @param [out] 
     * @return      
     */
    int deal_CliconnectEvent(int sfd,struct sockaddr_in* saveCin,fd_set* preadfds,int* pmaxfd)
    {

        struct sockaddr_in cin;
        socklen_t addrlen = sizeof(cin);
        int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
        if(newfd < 0){
            fprintf(stderr,"line:%d",__LINE__);
            perror("accept");
            return -1;
        }
        printf("[%s:%d] 客户端连接成功 newfd=%d  __%d__\n",\
        inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
        saveCin[newfd-3] = cin;

        FD_SET(newfd,preadfds);
        *pmaxfd = newfd>*pmaxfd ? newfd:*pmaxfd;

        return 0;
    }


    /*
     * function:    处理键盘输入事件
     * @param [ in] 
     * @param [out] 
     * @return      
     */
    int deal_keyboradEvent(fd_set readfds,struct sockaddr_in psaveCin[])
    {
        int sndfd;
        char buf[128];
        int res = scanf("%d %s",&sndfd,buf);
        while(getchar() != '\n');
        if(res != 2){
            printf("请输入正确的格式: fd string\n");
            return -1;
        }
        if(sndfd<0 || sndfd>1023 || FD_ISSET(sndfd,&readfds) == 0){
            printf("请输入正确的文件描述符");
            return -1;
        }
        if(send(sndfd,buf,sizeof(buf),0) < 0){
            perror("send");
            return -1;
        }
        printf("发送给[%s:%d] fd=%d客户端 成功 __%d__\n",inet_ntoa(psaveCin[sndfd-3].sin_addr),\
                                    ntohs(psaveCin[sndfd-3].sin_port),sndfd,__LINE__);
        return 0;
    }


    /*
     * function:    处理客户端交互事件
     * @param [ in] 
     * @param [out] 
     * @return      
     */

    int deal_CliTackEvent(int newfd,struct sockaddr_in saveCin[],fd_set* preadfds,int* pmaxfd)
    {
        //接收
        char buf[128]="";            
        bzero(buf,sizeof(buf));
        ssize_t res;
        res = recv(newfd,buf,sizeof(buf),0);
        if(res < 0){    
            fprintf(stderr,"line:%d",__LINE__);
            perror("recv");
            return -1;
        }
        else if(res == 0){
        printf("[%s:%d] 客户端断开 newfd=%d  __%d__\n",\
                        inet_ntoa(saveCin[newfd-3].sin_addr),ntohs(saveCin[newfd-3].sin_port),newfd,__LINE__);
        close(newfd);
        FD_CLR(newfd,preadfds);
        while(FD_ISSET(*pmaxfd,preadfds)==0 && (*pmaxfd--)>0);        
        return -1;
        }    
        printf("[%s:%d]newfd=%d :%s __%d__\n",\
                            inet_ntoa(saveCin[newfd-3].sin_addr),ntohs(saveCin[newfd-3].sin_port),newfd,buf,__LINE__);
    //发送
        strcat(buf," I GET IT!");
        if(send(newfd,buf,sizeof(buf),0) < 0){
            fprintf(stderr,"line:%d",__LINE__);
            perror("send");
            return -1;
        }
        printf("send success __%d__\n",__LINE__);        


        return 0;


    }

    头文件补充:


     

  • 相关阅读:
    基于Unet的环路滤波
    钟汉良日记:和鹤岗一样低房价的城市不止一个
    Linux内核源码分析 (B.4) 深度剖析 Linux 伙伴系统的设计与实现
    react ant design Upload 多文件上传 beforeUpload 会调用很多次,怎么只获取一次
    centos 7 升级Docker 与Docker-Compose 到最新版本
    GitHub知识追踪项目运行不来
    聚N-乙烯基乙酰胺接枝聚苯乙烯微球PNVA-g-PSt/磺化聚苯乙烯/壳聚糖复合微球探究
    异步加载 JavaScript
    CSS - 盒子模型
    【深度学习实践】基于深度学习的车牌识别(python,车牌检测+车牌识别)
  • 原文地址:https://blog.csdn.net/m0_72040461/article/details/138201144