2013-04-15 146 views
1

目前我正在使用单个服务器,单个客户端udp聊天应用程序。最初我使用了默认情况下的阻塞套接字。现在我想将套接字转换为非阻塞状态,以便客户端和服务器之间的通信可以在没有障碍的情况下完成... 我已经在服务器端实现了选择功能,但是它启动客户端获取发送一次,其中显示在服务器端的消息,随后客户端和服务器得到响应,所以现在我展示了如何有我实现在服务器端的select()函数:c中的非阻塞套接字

  //Declaring a non-blocking structure 
       fd_set readfds,writefds; 
      // clear the set ahead of time 
       FD_ZERO(&readfds); 
       FD_ZERO(&writefds); 
      // add our descriptor to the set 
       FD_SET(sd, &readfds); 
       FD_SET(sd, &writefds); 
       /value of sd+1 
       int n=sd+1; 

由于我想要接收和发送数据,我已经在循环中实现了选择功能:

   int client_length = (int)sizeof(struct sockaddr_in); 
       int rv = select(n, &readfds, NULL, NULL, NULL); 
       if(rv==-1) 
       { 
       printf("Error in Select!!!\n"); 
       exit(0); 
       } 
       else if(rv==0) 
       { 
       printf("Timeout occurred\n"); 
       } 
       else 
       if (FD_ISSET(sd, &readfds)) 
       { 
       int bytes_received = recvfrom(sd, buffer,SIZE, 0, (struct sockaddr *)&client, &client_length); 
       if (bytes_received < 0) 
       { 
       fprintf(stderr, "Could not receive datagram.\n"); 
       closesocket(sd); 
       WSACleanup(); 
       exit(0); 
       } 
       } 

还用于发送数据:

   fgets(buffer,SIZE,stdin); 
       int rv1 = select(n, &writefds, NULL, NULL, NULL); 
       if(rv1==-1) 
       { 
      printf("Error in Select!!!\n"); 
      exit(0); 
       } 
      else if(rv1==0) 
      { 
      printf("Timeout occurred\n"); 
      } 
      else 
      if(FD_ISSET(sd,&writefds)) 
        { 
        if(sendto(sd, buffer,strlen(buffer), 0, (struct sockaddr *) &client,client_length)<0) 
         { 
          printf("Error sending the file! \n"); 
          exit(1); 
         } 
        } 

       } 

所以我会很感激,如果somoone让我知道是否我做这个正确与否,如果是OK,然后会在客户端相同implelementation解决我的问题?

+0

记住'选择()'覆盖其输入,所以你在每次调用该函数的时间来重新创建'fd_set's(或复制这些文件)。我不确定这是否是你的问题,但它是'select()'代码的常见问题。 –

+0

@ Jonathan Leffler:我应该在循环中初始化“readfds”和“writefds”吗? –

+0

是的 - 你需要在循环中初始化'readfds'和'writefds',因为当你调用它时select()会修改它们。 –

回答

2

这是不正确的:

select(n, &writefds, NULL, NULL, NULL); 

的第二个参数是用来检查仅出于可读性。要检查可写性,使用第三个参数:

select(n, NULL, &writefds, NULL, NULL); 
+0

@ robertklep,谢谢:) –

+0

现在我有一个问题,如果我在客户端执行相同的事情侧,我应该能够创建一个无阻塞的udp聊天应用程序,因为到目前为止,我已经在服务器端完成了这一点,但我仍然感到阻塞套接字... –

+0

@AaymanKhalid你必须在两个双方,当然:) – robertklep