检查非阻塞发送是否成功。

5

我在一个套接字上进行了非阻塞发送调用,然后在另一个套接字上进行了阻塞接收。之后,我想检查非阻塞发送是否成功或失败。该如何实现?

    while (i)
    {
      retval = send (out_sd, s_message, strlen (s_message), MSG_DONTWAIT);
      retval = recv (client_sd, r_message, MSG_LEN, 0);
      r_message[retval] = '\0';
      /* Here I want to wait for the non-blocking send to complete */
      strcpy (s_message, r_message);
      strcpy (r_message, "");
      i--;
    }

能否使用回调函数? - andre
1
我不这么认为。在进入下一次迭代之前,只需要检查消息发送是否失败、成功或排队即可。 - phoxis
使用两个不同的变量来存储发送和接收的结果。 - alk
2个回答

5
你在某种程度上混淆了同步和异步IO,这通常会有点令人困惑,但我没有看到任何实际的问题。
为了避免硬轮询(即在循环中不断查看操作是否已完成),您应该使用select()等待您的通道/套接字可用于更多写操作。这将告诉您先前的操作已完成(或已完全由您的操作系统接管,这是相同的)。
select()函数是C语言中异步IO的基础,您应该在此处阅读相关内容,这里是我认为可能对您有用的示例。
请注意,select()支持读、写和异常事件,示例显示了一个读取选择器,您需要执行写入选择器。

是的,我已经混合使用同步和异步I/O,但是在不同的套接字中,我认为这样会很好地工作。每个进程都将执行此代码段,因此如果两者都阻塞,则会出现死锁。因此,我首先发送消息,然后等待接收。一个进程接收数据后,应该检查上一个非阻塞发送是否成功,然后再进入下一次迭代。 - phoxis
1
我不知道细节,但如果两个套接字连接了相同的两个程序,你确定不能只使用同步调用吗?比如程序A执行读取->写入->读取->等等,而程序B执行写入->读取->写入->等等。这通常是所做的,而且其中没有死锁。 - Federico Bonelli
1
如果您使用同步调用,当它们返回时,您会得到一个有意义的返回值来告诉您。如果您正在使用没有回调函数的异步模式,则唯一的方法是使用select(或poll / epoll)调用来等待该通道上的事件,并查看是否在“错误”事件之前出现了“再次写入可能”事件。 - Federico Bonelli
1
当然可以:在这个页面链接上,你可以看到一个等待读通道再次变得可用的示例。在示例中,设置了超时时间,在一定时间后即使没有发生任何事情也会返回(这很好,每秒甚至10秒左右)。 - Federico Bonelli
1
你显然想要使用写通道(以查看是否已完成写入)和错误(以查看是否发生了不良情况)来实现这一点。 - Federico Bonelli
显示剩余2条评论

1

send()函数将返回发送的字节数或者-1表示出现错误。

如果网络栈中有足够的缓冲区可以发送消息的一部分,retval将包含发送的字节数,这可能少于您要发送的字节数。如果网络栈缓冲区已满,则它将包含-1,并且errno将设置为EAGAINEWOULDBLOCK

在所有情况下,只要send()函数返回,发送调用就完成了。因此,在非阻塞发送完成之前,您不必等待任何其他地方,需要立即检查发送调用返回的返回值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接