2011-03-19 32 views
2

我想利用select系统调用来复STDIN和的sockfd(连接到服务器),使得我必须听都STDIN和的sockfd并根据所在服务器的数据可供阅读我必须继续。使用select()系统调用监听标准输入和

注:#定义STDIN 0

这是当我这样做会发生什么。

  • 我连接到服务器的常用方法[插座(),然后连接()]
  • 我添加STDIN和连接套接字描述符“的sockfd”到FD_SET(命名为“读集”),意味着阅读。
  • 然后我打电话给select()。
  • 使用FD_ISSET来确定哪个fd准备好读取。

这个设置的问题是FD_ISSET对于fd都是正确的。一旦我得到连接到服务器我看到FD_ISSET(的sockfd,&读集)始终是真实的,所以是FD_ISSET(STDIN,&读集)是否,服务器发送数据或不,或者如果我从键盘输入数据或没有。

我会做什么错?

/*连接成功*/

FD_ZERO(&connset); 

while(1) { 

    FD_SET(sockfd,&connset); /* add sockfd to connset */ 
    FD_SET(STDIN,&connset); /* add STDIN to connset */ 
    fdmax=sockfd; 

    if(select(fdmax+1,&readset,NULL,NULL,NULL)<0){ 
     fprintf(stdout, "select() error\n"); 
     exit(0); 
    }  

    /* select returned 
    * check which socket is set 
    */ 

    if(FD_ISSET(sockfd,&connset)) { 

     /* 
     * Server sends msglen 
     * client reads msg of length msglen 
     * client prints it to stdout 
     * client waits for next activity of its listen sockets 
     */ 
     size=4; 
     ptr=(char *)&msglen; 
     while(1) { 
      if((nread=recv(sockfd,ptr,size,0)),MSG_DONTWAIT) { 
       close(sockfd); 
       exit(0); 
      } 
      size-=nread; 
      ptr+=nread; 
     } 
     bytesToRead = ntohl(msglen); 
     readbuf = (char *)malloc(sizeof(char)*(bytesToRead+1)); 
     ptr=readbuf; 
     while(1) { 
      nread=recv(sockfd,ptr,bytesToRead,MSG_DONTWAIT); 
      if(nread<=0) { 
       close(sockfd); 
       exit(0); 
      } 
      bytesToRead-=nread; 
      ptr+=nread; 
     } 
     /* msg read successfully */ 
     *ptr='\0'; 
     fprintf(stdout, "in: %s\n",readbuf); 
     free(readbuf); 
    } 

    if(FD_ISSET(STDIN,&connset)) { 
     /* data at STDIN */ 
     fgets(buf,2,stdin); /* read the first newline char (<enter>) */ 
     fprintf(stdout,"Enter msg: "); 
     fgets(buf,MAXLEN,stdin); /* read the msg */ 
     buf[strlen(buf)-1]='\0'; 
     msglen = htonl((uint32_t)(strlen(buf)-1)); 
     ptr = (char *)&msglen; 
     bytesToSend = sizeof(uint32_t); 
     cnt = bytesToSend; 
     while(cnt>0) { 
      if((nsent=send(sockfd,ptr,cnt,0))>0) { 
       cnt-=nsent; 
       ptr+=nsent; 
      } 
      else { 
       fprintf(stdout,"send error\n"); 
       exit(0); 
      } 
     } 
     ptr=buf; 
     bytesToSend=(uint32_t)(strlen(buf)-1); 
     cnt=bytesToSend; 
     while(cnt>0) { 
      if((nsent=send(sockfd,ptr,cnt,0))>0) { 
       cnt-=nsent; 
       ptr+=nsent; 
      } 
      else { 
       fprintf(stdout,"send error\n"); 
       exit(0); 
      } 
     }  
    }  
} 
return 0; 

}

+0

您是否在__every__选择之前使用FD_SET?你能显示一些代码吗? – Ptival 2011-03-19 06:59:29

+0

如何关闭此问题? – Mir 2011-03-19 07:46:27

+0

发生编程错误。我现在正在讨论这个问题。谢谢。 – Mir 2011-03-19 08:02:59

回答

4

什么是STDIN?有其在<stdio.h>声明标准输入,是一个FILE *,而不是一个文件描述符所以不能在fdset和STDIN_FILENO,这是在<unistd.h>定义并且是一个文件描述符,因此可以与fdsets使用中使用。

顺便说一下,在<stdio.h>还有一个函数fileno(),它返回FILE *的文件描述符(取决于您的编译标志,您可能需要定义一些功能宏来获取声明)。

+0

#define STDIN 0 – Mir 2011-03-19 07:10:02

+1

fileno不是C标准,它只是POSIX。 unistd.h不是C标准,它只是POSIX。 – user411313 2011-03-19 07:17:45

+2

@ user411313。 fdsets和select是POSIX,我没有看到需要提及获取它们的参数,你需要一个POSIX函数。 – AProgrammer 2011-03-19 07:52:21