zoukankan      html  css  js  c++  java
  • [第三版]单线程多路复用

    第二版的问题

    第二版中存在一个问题, 当服务端进程意外终止, 如果客户端正阻塞在输入时, 那么无法接收到通知, 直到按下回车发送时报错才得知服务端已经关闭

    client

    #include "unp.h"
     
    void str_cli(FILE *fp,int sockfd);
     
    int main(int argc,char *argv[]){
        int sockfd,i;
        struct sockaddr_in servaddr;
     
        if(argc != 2)
            err_quit("usage: client <ip address>");
     
        sockfd=Socket(AF_INET,SOCK_STREAM,0);
        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_family=AF_INET;
        servaddr.sin_port=htons(13);
        inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
     
        Connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
     
        str_cli(stdin,sockfd);
     
        exit(0);
    }
     
    void str_cli(FILE *fp,int sockfd){
        char buff[MAXLINE];
        fd_set rset;
        int maxfdp1,stdineof;
        int n;
     
        stdineof=0;
        FD_ZERO(&rset);
        for(;;){
            if(stdineof == 0)
                FD_SET(fileno(fp),&rset);
            FD_SET(sockfd,&rset);
            maxfdp1=max(fileno(fp),sockfd)+1;
            Select(maxfdp1,&rset,NULL,NULL,NULL);
     
            if(FD_ISSET(sockfd,&rset)){
                if((n=Read(sockfd,buff,MAXLINE)) == 0){
                    if(stdineof == 1)
                        return;
                    else
                        err_quit("str_cli: server terminated prematurely");
                }
                Write(fileno(stdout),buff,n);
            }
     
            if(FD_ISSET(fileno(fp),&rset)){
                if((n=Read(fileno(fp),buff,MAXLINE)) == 0){
                    stdineof = 1;
                    shutdown(sockfd,SHUT_WR);
                    FD_CLR(fileno(fp),&rset);
                    continue;
                }
                writen(sockfd,buff,n);
            }
        }
    }
    

    serv

    几点说明:
    变量i,sockfd功能相近, 遍历时用
    client[FD_SETSIZE]用来保存所有需要读取的fd
    maxfd与client中最大的fd相同, maxi是这个最大fd在client中的下标
    nready保存当前已经准备就绪的fd数量

    #include "unp.h"
     
    int main(int argc, char *argv[]){
        int i,maxi,maxfd,listenfd,connfd,sockfd;
        int nready,client[FD_SETSIZE];
        ssize_t n;
        fd_set rset,allset;
        char buf[MAXLINE];
        socklen_t clilen;
        struct sockaddr_in servaddr,cliaddr;
     
        listenfd=Socket(AF_INET,SOCK_STREAM,0);
     
        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_family=AF_INET;
        servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
        servaddr.sin_port=htons(13);
     
        Bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
     
        Listen(listenfd,1024);
     
        maxfd=listenfd;
        maxi=-1;
        for(i=0;i<FD_SETSIZE;i++)
            client[i]=-1;
        FD_ZERO(&allset);
        FD_SET(listenfd,&allset);
     
        for(;;){
            rset=allset;
            nready=Select(maxfd+1,&rset,NULL,NULL,NULL);
     
            if(FD_ISSET(listenfd,&rset)){
                clilen=sizeof(cliaddr);
                connfd=Accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
     
                for(i=0;i<FD_SETSIZE;i++)
                    if(client[i] < 0){
                        client[i]=connfd;
                        break;
                    }
                if(i == FD_SETSIZE)
                    err_quit("too many clients");
     
                FD_SET(connfd,&allset);
                if(connfd > maxfd)
                    maxfd=connfd;
                if(i > maxi)
                    maxi=i;
                if(--nready <= 0)
                    continue;
            }
     
            for(i=0;i<=maxi;i++){
                if((sockfd=client[i]) < 0)
                    continue;
                if(FD_ISSET(sockfd,&rset)){
                    if((n=Read(sockfd,buf,MAXLINE)) == 0){
                        Close(sockfd);
                        FD_CLR(sockfd,&allset);
                        client[i]=-1;
                    }else
                        writen(sockfd,buf,n);
                    if(--nready <= 0)
                        break;
                }
            }
        }
    }
    
  • 相关阅读:
    Linux 查看本地ip
    php 利用debug_backtrace方法跟踪代码调用
    开源镜像站,vmware下载
    robots.txt 让搜索引擎不再收录网站
    PHP 面向对象 final类与final方法
    开源代码
    PHPStorm设置Ctrl+滚轮调整字体大小
    PHP array_chunk() 妙用
    第九节 JavaScript提取行间事件
    第八节 JavaScript函数的定义和执行
  • 原文地址:https://www.cnblogs.com/cfans1993/p/5883374.html
Copyright © 2011-2022 走看看