检查非阻塞发送是不是成功
Posted
技术标签:
【中文标题】检查非阻塞发送是不是成功【英文标题】:Check if a non-blocking send succeeded检查非阻塞发送是否成功 【发布时间】:2012-11-30 06:48:48 【问题描述】:我正在一个套接字上进行一次非阻塞发送调用,然后在另一个套接字上进行阻塞接收。之后我想检查非阻塞发送是成功还是失败。如何做到这一点?
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--;
【问题讨论】:
可以使用回调吗? 我不这么认为。在进入下一次迭代之前,只需要检查消息发送是否失败或成功或排队。 使用两个不同的 var/s 来存储 send/recv 的结果。 【参考方案1】:您以某种方式混合了同步和异步 IO,这通常有点令人困惑,但我在这里看不到任何实际问题。
为避免硬轮询(不断查看您的操作是否已在循环中完成),您应该使用 select() 来等待您的通道/套接字可用于更多写入操作。这将告诉您前一个已完成(或者它已完全由您的操作系统负责,这是相同的)。
select() 函数是 C 中异步 IO 的基础,您应该在 here 中了解它,this 是我认为可能对您有用的示例。
注意虽然select()支持读、写和异常事件,示例显示的是读选择,你想做一个写选择。
【讨论】:
是的,我混合了同步和异步 I/O,但在不同的套接字中,我认为这可以正常工作。每个进程都会执行这段代码,因此如果两者都阻塞,那么就会出现死锁。因此我首先发送消息,然后等待接收。一个进程接收到数据后,应该在进入下一次迭代之前检查最后一次非阻塞发送是否成功。 不知道具体情况,但是如果两个socket连接的是同一个2个程序,你确定不能只使用同步调用吗?就像程序 A 执行 READ -> WRITE -> READ -> 等,程序 B 执行 WRITE -> READ -> WRITE -> 等。这是通常的做法,并且没有死锁。 如果你使用同步调用,当它们返回时,你会得到一个有意义的返回值来告诉你。如果您使用没有回调的异步模式,唯一的方法是使用 select(或 poll/epoll)调用来等待该通道上的事件,并查看是否在“错误”之前出现“再次写入”事件" 事件。 当然:在此页面link 中,您有一个关于如何等待读取通道再次可用的示例。在示例中,超时设置为在一定时间后返回,即使没有发生任何事情(这很好,每秒甚至 10 秒左右)。 你显然想通过写入通道(查看它是否已完成写入)和错误(查看是否发生了不好的事情)来做到这一点【参考方案2】:send()
将返回发送的字节数或-1
以防出错。
如果网络堆栈中有足够的缓冲区可以从您的消息中发送至少一些字节,retval
将包含发送的字节数,这可能小于您要发送的字节数。如果网络堆栈缓冲区已满,它将包含-1
,并且errno
将被设置为EAGAIN
或EWOULDBLOCK
。
在所有情况下,发送调用一返回就完成。因此您不必在其他任何地方等待非阻塞发送完成,您需要在 send() 调用返回后立即检查返回值。
【讨论】:
以上是关于检查非阻塞发送是不是成功的主要内容,如果未能解决你的问题,请参考以下文章