【问题标题】:Blocking recvfrom with select system call使用 select 系统调用阻止 recvfrom
【发布时间】:2013-09-08 09:41:43
【问题描述】:

我有一个 UDP 客户端,它必须从两个不同的套接字接收。
我正在使用select 系统调用来复用recv 调用。

但我看到客户端在第二个 recv 调用中被阻止。

我该如何解决这个问题?

struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
int activity;

FD_ZERO(&socketfds);
FD_SET(usocket,&socketfds);
max_sd = std::max(max_sd, usocket);
FD_SET(msocket,&socketfds);
max_sd = std::max(max_sd, msocket);
rset = socketfds;

do
{
      rset = socketfds;
      activity = select( max_sd + 1 , &rset , NULL , NULL , &timeout);
}
while(activity<0 && errno == EINTR);

if ((activity < 0) && (errno!=EINTR))
{
     printf("select error");
}
if(FD_ISSET(usocket, &socketfds))
{
      int len;
      printf("Receiving from unicast socket..\n");
      if((len = recvfrom(usocket, dataBuffer, dataLength, 0, (struct sockaddr *)  
   &clientAddr, &clen) < 0) )
     {
           printf("Error reading message \n");
           close(msocket);
           exit(-1);
     }
     else
     {
             printf("Size of message: %d\n", strlen(dataBuffer));
             handleMessage(dataBuffer);
     }
}
if(FD_ISSET(msocket, &socketfds))
{
     printf("Receiving from multicast socket..\n");
     if((recvfrom(msocket, dataBuffer, dataLength, 0, (struct sockaddr *)  
   &multicastClientAddr, &mlen) < 0) )
    {
       printf("Error reading message \n");
       close(msocket);
       exit(-1);
    }
    else
    {
      printf("Message from server:%s\n", dataBuffer);
      handleMessage(dataBuffer);
    }
}

【问题讨论】:

    标签: linux sockets select udp recv


    【解决方案1】:

    您需要检查通过 select 返回(修改)的 rset 以查看套接字是否已准备好读取 - 这些位将始终设置在 socketfds 中,因为这是您要等待的主要套接字集。所以改变

    if(FD_ISSET(Xsocket, &socketfds))
    

    行到

    if(FD_ISSET(Xsocket, &rset))
    

    【讨论】:

      【解决方案2】:

      我认为问题在于你没有考虑超时,超时时选择return 0。在这种情况下,当返回 0 时,我不知道 rset 结构将如何,可能未定义或未触及。如果您想无限等待,请使用 NULL 代替超时。

      【讨论】:

        【解决方案3】:

        您应该更改 do-while 循环的条件。仅当存在某些事件时,Select 才会返回非零值(具有事件的 fd 的数量)。在您的情况下,它将返回已读取事件的 fd 数量。因此,如果其中一个 fd 具有读取事件,则 select() 将返回 1,如果两者都具有读取事件,则 select 将返回 2。如果 (activity == 0),则具有读取事件的 fd 数量是零,所以如果你调用 recvfrom(),那自然会阻塞。

        while(activity <= 0 && errno == EINTR);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-14
          • 2012-10-31
          • 1970-01-01
          相关资源
          最近更新 更多