套接字:我的select()函数逻辑具有未定义的行为

时间:2015-04-04 17:35:43

标签: c++ c sockets

我实现了一个从一个套接字接收并从另一个套接字发送/接收的程序。

为此我使用select()的轮询,在套接字1中,我以高数据速率接收数据,而在另一个套接字中,我接收定期消息并请求从第一个套接字接收数据。

当没有“来自套接字2”的请求将数据从套接字1委托给socket2时,我从套接字1正常接收数据并且没有问题。但是,假设我收到两个请求“套接字2”而数据正在套接字1中接收,第二个请求打破了数据接收,好像它再也无法跟上速率“速率不高真的只有150赫兹” 。

我在main()中做的伪代码:

fd_set readfds, rd_fds, writefds, wr_fds;
struct timeval tv;

do
  {
    do
      {
        rd_fds = readfds;
        wr_fds = writefds;
        FD_ZERO (&rd_fds);
        FD_SET (sock1, &rd_fds);
        FD_SET (sock2, &rd_fds);
        FD_SET (sock1, &wr_fds);
        tv.tv_sec = 0;
        tv.tv_usec = 20;
        int ls = sock2 + 1;
        rslt = select (ls, &rd_fds, &wr_fds, NULL, &tv);
      }
    while (rslt == -1 && errno == EINTR);


    if (FD_ISSET (sock1, &rd_fds))
      {
        rs1 = recvfrom (sock1, buff, size of the buff, ....);
        if (rs1 > 0)
          {
             if (rs1 = alive message)
                {
                /* system is alive; */
                }
             else if (rs1 == request message)
               {
                /* store Request info (list or vector) */
               }
             else {}
          }
     }

    if (FD_ISSET (StructArg.sock2, &rd_fds))
      {
        rs2 = recv (sock2, ..., 0);
        if (rs2 > 0)
          {
            if ( /* Message (high rate) is from sock 2 */ )
              {
                /* process this message and do some computation */

                int sp1 = sendto (sock1, .....);

                if (sp1 < 0)
                  {
                    perror ("Failed data transmission ");
                  }
                else
                  {
                    /* increase some counters */
                  }
              }
          }
      }

    if (FD_ISSET (sock1, &wr_fds))
      {
        /*
           if there info stored in the list
           do some calculaitons then send to sock 1
         */
        if (sendto (sock1, ... ...) < 0)
          {
            perror ("Failed data transmission");
          }
        else
          {
            /* increase counter */
          }

      }

    FD_CLR (sock1, &rd_fds);
    FD_CLR (sock2, &rd_fds);
  }
while (1);

同样,问题是,如果从sock2收到请求,为什么从sock1接收中断,而我从sock1(快速消息)接收,我期望输出中的交错消息基于消息中的时间戳。

2 个答案:

答案 0 :(得分:0)

请注意,除非您使用O_NONBLOCK选项创建套接字,否则几乎所有套接字函数都可以阻止执行:

http://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html

除非你使用MSG_WAITALL,否则你还必须处理recvfrom只给你部分读取的情况:

http://pubs.opengroup.org/onlinepubs/009695399/functions/recvfrom.html

就个人而言,我使用多线程实现,它可以让线程坐下来等待每个套接字上的数据。

关于你的最后一个问题:

  

为什么从sock2收到请求时sock1的接收被中断,而我从sock1(快速消息)收到请求时,我希望输出中的交错消息基于消息中的时间戳。

您是网络堆栈实现的奴隶,几乎不保证在一个套接字上相对于另一个套接字发送或接收数据。您只能保证套接字中的数据正确排序。

答案 1 :(得分:0)

  

我希望输出中的交错消息基于消息中的时间戳。

你的期望没有基础。如果任一套接字缓冲区中都有数据,select()将触发。这就是你可以信赖的全部。您无法保证在多个套接字之间观察和订购时间戳。