如何在C?中刷新UDP套接字的输入缓冲区(如果存在这种情况)?
我正在开发嵌入式Linux环境并使用C创建一些本机应用程序。这些嵌入式计算机在同一网络上有几个,当其中一个发生事件时(我们称之为WHISTLE-BLOWER),WHISTLE-BLOWER应该向网络广播地址发送网络消息,以便所有机器都在网络(包括WHISTLE-BLOWER)知道事件并根据它执行一些操作。 我正在使用UDP套接字......
这是伪代码:
main
{
startNetworkListenerThread( networkListenerFunction );
while( not received any SIGTERM or such )
{
localEventInfo = checkIfTheLocalEventOccured();
broadcastOnNetwork( localEventInfo );
}
}
networkListenerFunction
{
bindSocket;
while( not SIGTERM )
{
// THIS IS WHERE I WANT TO FLUSH THE RECV BUFFER...
recv_data = recvfrom( socket );
if( validate recv data )
{
startExecuteLocalAction;
sleep( 5 );
stopExecuteLocalAction;
}
}
}
我期望并希望使用此代码的方式是:
1. LOCAL_EVENT occured
2. Broadcasted LOCAL_EVENT_INFO on network
3. All machines received EVENT_INFO, including the original broadcaster
4. All machines started executing the local action, including the original broadcaster
5. All machines' network listener(thread)s are sleeping
6. Another LOCAL_EVENT2 occured
7. Since all machines' listener are sleeping, LOCAL_EVENT2 is ignored
8. All machines' network listener(thread)s are now active again
9. GO BACK TO 1 / RESTART CYCLE
RESULT = TOTAL 2 EVENTS, 1 IGNORED
它实际运作的方式是:
1. LOCAL_EVENT occured
2. Broadcasted LOCAL_EVENT_INFO on network
3. All machines received EVENT_INFO, including the original broadcaster
4. All machines started executing the local action, including the original broadcaster
5. All machines' network listener(thread)s are sleeping
6. Another LOCAL_EVENT2 occured
7. Eventhough all machines' listener are sleeping; LOCAL_EVENT2 is queued SOMEHOW
8. All machines' network listener(thread)s are now active again
9. All machines received EVENT_INFO2 and executed local actions again, slept and reactivated
10. GO BACK TO 1 / RESTART CYCLE
RESULT = TOTAL 2 EVENTS, 0 IGNORED
tl,dr:发送到已经绑定的套接字的数据包/消息/ UDP广播,父母线程在交付时刻正在休眠;以某种方式排队/缓冲并在所述套接字上的下一次'recvfrom'呼叫中发送。
我希望忽略那些UDP广播,所以我想在调用recvfrom之前刷新接收缓冲区(显然不是我给recvfrom方法作为参数的那个)。我怎样才能做到这一点?或者我应该遵循什么样的路径?
答案 0 :(得分:3)
请注意,“冲洗”的概念仅适用于输出。刷新清空缓冲区并确保其中的所有内容都已发送到目标。关于输入缓冲区,数据已经在其目的地。可以读取或清除输入缓冲区,但不能“刷新”。
如果您只想确保已读取输入缓冲区中的所有内容,那么您要查找的是非阻塞读取操作。如果您尝试并且没有输入,则应该返回错误。
答案 1 :(得分:1)
套接字在TCP / IP堆栈中有一个 接收缓冲区 。它本质上是收到的数据报的FIFO。 TCP和UDP处理该队列的方式不同。当您在UDP套接字上调用recv(2)
时,从该缓冲区中出列单个数据报。 TCP根据序列号将数据报排列成字节流。当接收缓冲区溢出时,堆栈会丢弃数据报。在这种情况下,TCP尝试重新发送。 UDP没有。除了读取套接字或关闭套接字之外,接收缓冲区没有明确的“刷新”功能。
您的应用程序中存在固有的竞争条件,看起来您正试图使用错误的工具(TCP / IP堆栈)来解决它。 我认为你应该做的是为应用程序定义一个干净的状态机。处理当前状态下有意义的事件,忽略不存在的事件。
另一个需要注意的是使用多播而不是广播。它涉及的有点多,但您可以通过加入/离开多播组来更好地控制“订阅”。