6

我正在 Linux 上编写 C++ 应用程序。我的应用程序有一个 UDP 服务器,它在某些事件上向客户端发送数据。UDP 服务器还从客户端接收一些反馈/确认。

为了实现这个应用程序,我使用了一个 UDP 套接字(例如int fdSocket)来发送和接收来自所有客户端的数据。我将这个 socked 绑定到端口 8080 并将套接字设置为 NON_BLOCKING 模式。

我创建了两个线程。在一个线程中,我等待某个事件发生,如果发生事件,那么我使用 fdsocket 将数据发送到所有客户端(在 for 循环中)。

在另一个线程中,我使用fdSocket接收来自客户端的数据 ( recvfrom())。该线程计划每 4 秒运行一次(即每 4 秒调用一次recvfrom()以从套接字缓冲区检索数据。由于它处于非阻塞模式,recvfrom()如果没有可用的 UDP 数据,该函数将立即返回,然后我会去睡眠 4 秒)。

来自所有客户端的 UDP 反馈/确认有一个固定的有效负载,其大小为 20 字节。

现在我有两个与此实现相关的问题:

  1. 使用同一个套接字与多个客户端发送/接收 UDP 数据是否正确?
  2. 如何找到我的应用程序在没有 UDP 套接字缓冲区溢出的情况下可以处理的最大 UDP 反馈/确认数据包数(因为我每 4 秒读取一次,如果我在这 4 秒内收到很多数据包,我可能会丢失一些数据包,即,我需要找到我可以安全处理的数据包/秒的速率)?

我尝试fdsocket使用函数调用获取我的套接字 ()的 Linux 套接字缓冲区大小getsockopt(fdsocket,SOL_SOCKET,SO_RCVBUF,(void *)&n, &m);。从这个函数中,我发现我的套接字缓冲区大小为 110592。但我不清楚这个套接字缓冲区中将存储哪些数据:它是否只存储 UDP 有效负载或整个 UDP 数据包或事件整个以太网数据包?我参考了这个链接以获得一些想法,但感到困惑。

目前我的代码有点脏,我会尽快清理并在这里发布。

以下是我在发布此问题之前提到的链接。

  1. Linux 网络
  2. UDP SentTo 和 Recvfrom 最大缓冲区大小
  3. UDP Socket 缓冲区溢出检测
  4. UDP广播和单播通过同一个套接字?
  5. 在多个线程中从同一个 UDP 套接字发送
  6. 如何在 C 中刷新 UDP 套接字的输入缓冲区?
  7. 如何找到linux的套接字缓冲区大小
  8. 如何获取 UDP 套接字的排队数据量?
4

3 回答 3

6

以四秒的固定间隔读取套接字肯定会让您丢失数据包。非阻塞 I/O 的传统可靠方法是解复用器系统调用select(2)// poll(2)epoll(7)看看您是否可以使用这些来捕获/响应您的其他事件。

另一方面,由于您已经在使用线程,您可以在没有四秒睡眠的情况下阻塞recv(2) 。

阅读史蒂文斯的解释SO_RCVBUF

于 2012-07-12T12:19:45.177 回答
3

问:使用同一个套接字与多个客户端发送/接收 UDP 数据是否正确?

A:是的,没错。

问:如何找到我的应用程序在没有 UDP 套接字缓冲区溢出的情况下可以处理的最大 UDP 反馈/确认数据包数(因为我每 4 秒读取一次,如果我在这 4 秒内收到很多数据包,我可能会丢失一些数据包,即,我需要找到速率:noofpackets/sec 我可以安全处理)?

答:瓶颈可能是网络带宽、CPU 或内存。您可以简单地进行测试,使用客户端向服务器发送连续编号的 ACK,并验证服务器是否存在丢包。

于 2012-07-12T12:17:25.173 回答
3

您可以看到允许的最大缓冲区大小:

sysctl net.core.rmem_max

您可以通过以下方式设置可以使用的最大缓冲区大小:

sysctl -w net.core.rmem_max=8388608

您还可以通过使用 setsockopt 并更改 SO_RCVBUF 在运行时设置缓冲区大小(不超过上述最大值)。您可以通过查看 /proc/net/udp 查看缓冲区级别。

缓冲区用于存放UDP头和应用程序数据,其余属于较低级别。

于 2012-07-12T12:21:29.150 回答