select()API

WJnuHhail發表於2024-06-13

編寫TCP客戶端和服務端程式,客戶端透過多路IO複用同時處理標準輸入(檔案描述符為0)和套接字。當輸入為quit時程式結束;當透過套接字收到對方訊息時把收到的訊息再次轉發給對方,伺服器端需透過select()監控listenfd和accept()後建立的新的套接字newfd, 可只寫select()相關的主要程式碼。


        perror("listen");
        return -1;
    }
     //接受連線--accept阻塞
    //接收客戶端資料--recv阻塞
     //select多路複用
     fd_set readfds;
     //定義讀檔案描述符集合
    int  cfds[50]={0};
     //儲存所有客戶端的套接字
    while(1)
    {
        int maxfd = sockfd;
        //清空集合
        FD_ZERO(&readfds);
        FD_SET(sockfd,&readfds);
          //把sockfd新增到readfds集合中
          //把客戶端的套接字也新增到集合中
        for(int i=0; i<50; i++)
        {
              if(cfds[i] != 0)//如果不等於0就說明這個空間儲存了套接字 
           {
                FD_SET(cfds[i],&readfds);
                maxfd = maxfd>cfds[i]?maxfd:cfds[i];
            }
        }        //select用監聽readfds裡面的所有檔案描述符,
        //如果某一個或多個描述符有響應就跳出select函式
        ret = select(maxfd+1,&readfds,NULL, NULL, NULL);
        if(ret < 0)
        {
            perror("select");
        }
        //判斷是否是sockfd有資料---說明有客戶端連線
        if(FD_ISSET(sockfd, &readfds))
        { 
               //接受連線
            int clientfd = accept(sockfd, NULL,NULL);
            if(clientfd < 0)
            {
                perror("accept");
            }            //把客戶端套接字儲存到cfds陣列中
            for(int i=0; i<50; i++)
            {
                if(cfds[i] == 0)//判斷放在沒有使用的空間中
                {
                     cfds[i] = clientfd;
                     break;
                }
            }
         }        //判斷是否是客戶端有資料
        for(int i=0; i<50; i++)
        {
            //判斷套接字是否存在,並且是否有資料到達
            if(cfds[i] != 0 && FD_ISSET(cfds[i], &readfds))
            { 
                     //接收客戶端資料
                char buffer[128]={0};
                int size = recv(cfds[i], buffer, 128, 0);
                if(size<=0)
                {
                    printf("有客戶端掉線\n");
                    close(cfds[i]);
                    cfds[i] = 0;
                }
                //把接收到的資訊轉發給客戶端自己
                     size = send(cfds[i],buffer,size,0);

            }
        }
    }
     printf("有客戶端連線\n");
    close(sockfd);
 }

相關文章