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

Sockets: my select() function logic has undefined behavior

本文关键字:未定义 函数 我的 select 套接字      更新时间:2023-10-16

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

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

当没有"来自套接字2"的请求将数据从套接字1委托给套接字2时,我从套接字1正常接收数据,没有问题。然而,假设我在套接字1中接收数据时收到了两个请求"套接字2",第二个请求中断了数据接收,好像它无法再跟上速率"速率不高,实际上只有150 Hz"。

我在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接收(快速消息),我希望基于消息中的时间戳在输出中交错消息。

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

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

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

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

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

至于你的最后一个问题:

如果从sock2接收到请求,为什么从sock1的接收会中断,而我从sock1接收(快速消息),我希望根据消息中的时间戳在输出中交错消息。

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

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

你的期望是没有根据的。如果任一套接字接收缓冲区中有数据,则select()将激发。这就是你所能依赖的。你不能保证在多个套接字之间观察和排序时间戳。