linux - 如何告诉另一个线程一个线程在 recv() 调用中*现在*

标签 linux multithreading sockets system-calls recv

有一个带有外部连接(以太网)设备的嵌入式 Linux 系统,一旦通过命令启动它就会发送大量 UDP 数据。 启动时,我有一个线程在程序运行时的剩余时间持续接收 UDP 数据。 正如我所看到的,为了原则上的可靠性,不仅仅是偶然的,必须确保 UDP 接收循环必须在外部数据源启动之前首先调用 recv() ,否则第一个数据包可能会丢失,取决于调度程序的突发奇想。 (这一切都在一个非常本地的、有目的的简单网络设置中——数据包丢失通常不是问题,也没有得到处理——速度为王) 目前,就在调用该 UDP 接收代码之前,我启动了一个延迟一段时间的临时线程,然后使数据源能够发送 UDP 数据。 这是目前“确保”第一个 UDP 数据包在接收线程“准备好”时到达的方法,即在 recv() 调用中,操作系统等待数据。

即使我,比如说,在第一次调用 recv() 之前设置一个条件变量来告诉程序的其余部分“好的,你现在可以启用数据源,我准备好了”——它可以,理论上,在信号标记和实际调用 recv 之间(或/和 recv 的内部实际上准备就绪)之间存在一些调度引起的延迟。

有没有比使用一些“经验延迟时间”更优雅/正确的方法来解决这个问题?

用于说明的伪代码:

// ******** main thread ********
thread delayed( [&]{ sleepMs(500); enableUdpDataSource(); } );
thread udpRecv( [&]{ udpRecvUntilTimeout() } );
delayed.join();
udpRecv.join();
return 0;

// ******** UDP thread ********
void udpRecvUntilTimeout()
{
  udpInit(); // set up socket, buffer sizes etc

  while (shouldRun)
  {
    // recv() needs to be "armed" *before* the data source is enabled.
    // If I set a condition variable for another thread right here,
    // there may be a scheduling intervention between it and the actual
    // engaging of recv() - when the other thread happily enables the datasource.
    int received = recv( sockFd, buf, maxlen, 0 );
    timeoutWatchdogReset();
    processReceivedData();
  }
}

最佳答案

在较早的版本中,我建议对 bind 的调用是可选的,但当然不是。您必须调用它才能告诉内核打开哪个 UDP 端口。 bind 之后,内核将缓冲传入的 UDP 数据包,如果您对客户端网络细节不感兴趣,可以调用 recv(否则,调用 recvfrom).

沿着这些线的东西:

char buf[1500];
struct sockaddr_in addr;

int sd = socket(AF_INET, SOCK_DGRAM, 0);

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons((unsigned short) 1234); // UDP port

bind(sd, (struct sockaddr *)&addr, sizeof(addr));

// start data sending thread

sleep(1); // for testing

recv(sd, buf, 100, 0);

但是 UDP 没有任何保证;您可能仍然会丢失数据包(例如,如果发送方使接收方过载)

关于linux - 如何告诉另一个线程一个线程在 recv() 调用中*现在*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57270559/

相关文章:

java - 小程序中的netty抛出AccessControlException

python - 如果循环内满足条件,如何在 while 循环中并行调用函数?

linux - 如何更新从源代码构建的程序

linux - 如何知道 "cat"命令显示的行数?

c++ - 将数据结构传递给不同的线程

node.js - 在NestJs中使用Socket IO加入并发布到房间

python - Linux 中的用户空闲时间

Linux 网络堆栈队列

c# - Interlocked.CompareExchange 是否使用内存屏障?

python - 如何正确停止 python 线程?