2011-01-25 77 views
4

我正在做一个C++项目,需要一个服务器创建一个新的线程来处理连接,每次accept()返回一个新的套接字描述符。我使用select来决定连接尝试何时发生以及客户端通过新创建的客户端套接字(接受创建的客户端套接字)发送数据的时间。因此,有两个函数和两个选择 - 一个用于轮询专用于侦听连接的套接字,一个用于轮询在新连接成功时创建的套接字。select()总是返回1; TCP连接套接字问题在C++

第一种情况的行为是我所期望的 - FD_ISSET仅在请求连接时才为侦听套接字的ID返回true,并且在下次连接尝试之前为false。第二种情况不起作用,即使代码与不同的fd_set和套接字对象完全相同。我想知道这是否源于TCP套接字?由于它们的流畅性质,这些套接字在被选择器轮询时是否总是返回true?

//working snippet 

struct timeval tv; 
tv.tv_sec = 0; 
tv.tv_usec = 500000; 
fd_set readfds; 
FD_ZERO(&readfds); 
FD_SET(sid,&readfds); 

//start server loop 
for(;;){ 

    //check if listening socket has any client requrests, timeout at 500 ms 
    int numsockets = select(sid+1,&readfds,NULL,NULL,&tv); 
    if(numsockets == -1){ 
     if(errno == 4){ 
      printf("SIGINT recieved in select\n"); 
      FD_ZERO(&readfds); 
      myhandler(SIGINT); 
     }else{ 
      perror("server select"); 
      exit(1); 
     } 
    } 

    //check if listening socket is ready to be read after select returns 
    if(FD_ISSET(sid, &readfds)){ 
     int newsocketfd = accept(sid, (struct sockaddr*)&client_addr, &addrsize); 
     if(newsocketfd == -1){ 
      if(errno == 4){ 
       printf("SIGINT recieved in accept\n"); 
       myhandler(SIGINT); 
      }else{ 
       perror("server accept"); 
       exit(1); 
      } 
     }else{ 
      s->forkThreadForClient(newsocketfd); 
     } 
    } 






//non working snippet 

//setup clients socket with select functionality 
struct timeval ctv; 
ctv.tv_sec = 0; 
ctv.tv_usec = 500000; 
fd_set creadfds; 
FD_ZERO(&creadfds); 
FD_SET(csid,&creadfds); 



for(;;){ 

    //check if listening socket has any client requrests, timeout at 500 ms 
    int numsockets = select(csid+1,&creadfds,NULL,NULL,&ctv); 
    if(numsockets == -1){ 
     if(errno == 4){ 
      printf("SIGINT recieved in client select\n"); 
      FD_ZERO(&creadfds); 
      myhandler(SIGINT); 
     }else{ 
      perror("server select"); 
      exit(1); 
     } 
    }else{ 
     printf("Select returned %i\n",numsockets); 
    } 

    if(FD_ISSET(csid,&creadfds)){ 


     //read header 
     unsigned char header[11]; 
     for(int i=0;i<11;i++){ 
      if(recv(csid, rubyte, 1, 0) != 0){ 
       printf("Received %X from client\n",*rubyte); 
       header[i] = *rubyte; 
      } 
     } 

任何帮助,将不胜感激。


感谢您的回复,但我不认为它有很多待处理的循环内的超时值。我对它进行了测试,即使电视被重置并且fd_set在每次服务器循环时被清零,select仍然立即返回1。我觉得select对待我的TCP套接字有问题。任何时候我设置选择最高的套接字ID来包含我的TCP套接字,它会立即返回该套接字集。另外,客户端不发送任何东西,只是连接。

+0

您能否修复您的缩进以便它看起来正确?所有的代码都像这样左边的边缘被冲上去很难。 – 2011-01-25 07:41:46

+0

你说这是行不通的。但它是做什么呢? – BatchyX 2011-01-25 08:38:16

回答

6

有一件事你必须是你叫select()之前的tv值每次重置为所需的超时。 select()函数更改tv中的值以指示在从函数返回后,超时中剩余多少时间。如果你没有这样做,你的select()调用将最终使用零的超时,这是不高效的。

其他一些操作系统以不同的方式实现select(),使得它们不会更改tv的值。 Linux确实改变了它,所以你必须重置它。

3

移动

FD_ZERO(&creadfds); 
FD_SET(csid,&creadfds); 

进入循环。函数select()报告此结构中的结果。您已经检索到结果

FD_ISSET(csid,&creadfds);