簡體   English   中英

Unix C程序-套接字和選擇函數

[英]Unix C program---socket and select function

我只是開始學習Unix C編程,還有一個我無法解決的問題。 在此程序中,我制作了一個具有套接字和選擇功能的簡單服務器。 當我使用不同的終端啟動嘗試連接服務器的客戶端程序時,服務器可以接受新客戶端並成功建立連接(根據我的代碼打印一句話)。 但是,當我嘗試將客戶端程序中的消息發送到客戶端程序中的服務器(通過scanf()和send())時,服務器只是阻塞在那里,無法接收到任何消息。 您能幫我發現程序中的缺陷嗎? 非常感謝您的任何建議! 這是我的服務器程序的代碼(我認為客戶端程序沒有問題):

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/types.h>
  5 #include <sys/socket.h>
  6 #include <netinet/in.h>
  7 #include <string.h>
  8 #include <fcntl.h>
  9 #include <sys/select.h>
 10 //all kinds of header 
 11 main(){
 12     int sfd;  //server's file descriptor 
 13     int fdall[100];  //array for client descriptor 
 14     int count=0;  //total number of clients
 15     int maxfd=0;   // max value of all descriptors
 16     char buf[1024]={0}; //used for receiving message from client, by recv()
 17     fd_set fds;  // readset in select()
 18     sfd=socket(AF_INET,SOCK_STREAM,0);
 19 
 20     struct sockaddr_in add;
 21     add.sin_family=AF_INET;
 22     add.sin_port=htons(9999);
 23     add.sin_addr.s_addr=inet_addr("192.168.122.1");
 24     int i,j,r;
 25 
 26     r=bind(sfd,(struct sockaddr*)&add,sizeof(add));
 27     if(r==-1) printf("bind:%m\n"),exit(-1);
 28     else puts("bind ok!");
 29     listen(sfd,10);
 30 
 31     while(1){
 32         FD_ZERO(&fds);
 33         maxfd=0;
 34         FD_SET(sfd,&fds);
 35         maxfd=maxfd>sfd?maxfd:sfd;
 36         for(i=0;i<100;i++){
 37             fdall[i]=-1;
 38         }
 39         r=select(maxfd+1,&fds,0,0,0);
 40         if(FD_ISSET(sfd,&fds)){
 41             fdall[count]=accept(sfd,0,0);
 42             puts("new client!");
 43             count++;
 44         }
 45         for(i=0;i<count;i++){
 46             if(FD_ISSET(fdall[i],&fds)!=-1&&fdall[i]!=-1){
 47                 r=recv(fdall[i],buf,1023,0);
 48                 for(j=0;j<count;j++){
 49                     if(fdall[j]!=-1){
 50                         send(fdall[j],buf,r,0);
 51                     }
 52                 }
 53             }
 54         }
 55     }
 56 }

您不能使用scanf讀取套接字。 scanf將從STDIN讀取; 這就是導致您被阻止的原因。 您也不能使用fscanf ,因為這將需要FILE * ,並且盡管可以使用freopen從套接字創建文件,但它將假定它可以坐在那里並read其內容,而不是使用select

您需要做的是從套接字read緩沖區。 當您有適當數量的數據(也許用換行符分隔)時,請使用sscanf (請注意其他s ),並確保要解析的字符串是NUL終止的。

您當前的代碼有幾個問題:

1.) fds集中始終只有一個套接字集。 它是您正在偵聽新連接的套接字。 您可能還希望將所有連接到客戶端的套接字放在此處。

2.)測試FD_ISSET(fdall[i],&fds)!=-1沒有意義。 FD_ISSET(fdall [i],&fds)類似於布爾值,僅將相等性/差異性測試為零。

3.)測試FD_ISSET(fdall[i],&fds)始終為零,因為您已經清除了fds所有值( sfd除外)。 請注意, select從不將文件描述符添加到集合中。 它刪除了將在下一個I / O操作中阻塞的那些。

4.)在大循環的每次通過中,您都將fdall[i]設置為-1盡管先前的值可能是打開的套接字,並且您永遠不會關閉套接字。

在我看來,您需要重新考慮基本功能。 您應在大循環之前將fdall[i]設置為-1 在循環中,應將fdall[i]所有套接字添加到fds 當有新的客戶端連接時,您應該跳過下一個循環迭代,以避免使用此新套接字測試FD_ISSET(該套接字可能超出maxfd調用select的maxfd值)。 希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM