【问题标题】:Non blocking socket in cc中的非阻塞套接字
【发布时间】:2013-04-15 05:56:38
【问题描述】:

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

            //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;

由于我想同时接收和发送数据,所以我在循环中实现了select函数:

                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);
                         }
                  }

                }

所以如果有人让我知道我是否做对了,我真的很感激,如果这没问题,那么客户端的相同实现会解决我的问题吗?

【问题讨论】:

  • 请记住 select() 会覆盖其输入,因此您必须在每次调用该函数(或复制它们)时重新创建 fd_sets。我不确定这是否是您的问题,但这是select() 代码的常见问题。
  • @Jonathan Leffler:那么我应该在循环中初始化“readfds”和“writefds”吗?
  • 是的 - 你需要在循环中初始化 readfdswritefds 因为 select() 在你调用它时会修改它们。
  • 好的,我在客户端也实现了同样的东西,但它仍然作为一个阻塞应用程序工作:(
  • 请让我知道我要去哪里或者它是否是正确的方法......我看到了 select() 的例子,它基本上处理了两个套接字来检查他们是否输入数据或不是……

标签: c sockets udp


【解决方案1】:

这是不正确的:

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

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

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

【讨论】:

  • 现在我有一个问题,如果我在客户端实现同样的事情,我是否能够创建一个非阻塞 udp 聊天应用程序,因为到目前为止我已经在服务器端完成了这个但我仍然有阻塞套接字的感觉......
  • @AaymanKhalid 当然,你必须在双方都实现它:)
  • @robertkelp,我有,但它仍然作为一个阻塞应用程序工作,客户端和服务器仍然一一通信,如果我尝试从一侧多次发送数据,下次它会显示: (
  • @AaymanKhalid 我认为您需要将两个 select 语句合并为一个:select(n, &amp;readfds, &amp;writefds, NULL, NULL)
  • @robertklep,如果我按照你说的做,服务器在没有客户端连接的情况下启动时会打印一整套冗余数据!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-31
  • 2013-10-15
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 2011-12-27
相关资源
最近更新 更多