【发布时间】:2012-07-12 03:49:42
【问题描述】:
我正在 Linux 上编写 C++ 应用程序。我的应用程序有一个 UDP 服务器,它在某些事件上向客户端发送数据。 UDP 服务器还会收到来自客户端的一些反馈/确认。
为了实现这个应用程序,我使用了一个 UDP 套接字(例如 int fdSocket)来发送和接收来自所有客户端的数据。我将这个 socked 绑定到端口 8080 并将套接字设置为 NON_BLOCKING 模式。
我创建了两个线程。在一个线程中,我等待某个事件发生,如果发生事件,则使用 fdsocket 将数据发送到所有客户端(在 for 循环中)。
在另一个线程中,我使用fdSocket 从客户端(recvfrom())接收数据。该线程计划每 4 秒运行一次(即每 4 秒它将调用 recvfrom() 以从套接字缓冲区检索数据。由于它处于非阻塞模式,如果没有 UDP 数据,recvfrom() 函数将立即返回可用,然后我会去睡觉 4 秒)。
来自所有客户端的 UDP 反馈/确认有一个固定的有效负载,大小为 20 字节。
现在我有两个与此实现相关的问题:
- 使用同一个socket发送/接收UDP数据是否正确 有多个客户?
- 如何找到我的应用程序在没有 UDP 套接字缓冲区溢出的情况下可以处理的最大 UDP 反馈/确认数据包数(因为我每 4 秒读取一次,如果我 在这 4 秒内收到很多数据包我可能会丢失一些数据包,即,我需要找到可以安全处理的数据包/秒速率)?
我尝试使用函数调用 getsockopt(fdsocket,SOL_SOCKET,SO_RCVBUF,(void *)&n, &m); 获取我的套接字 (fdsocket) 的 Linux 套接字缓冲区大小。从这个函数中,我发现我的套接字缓冲区大小为 110592。但我不清楚这个套接字缓冲区中将存储哪些数据:它是否只存储 UDP 有效负载或整个 UDP 数据包或事件整个以太网数据包?我参考了这个link 来获得一些想法,但很困惑。
目前我的代码有点脏,我会尽快清理并在这里发布。
以下是我在发布此问题之前参考的链接。
- Linux Networking
- UDP SentTo and Recvfrom Max Buffer Size
- UDP Socket Buffer Overflow Detection
- UDP broadcast and unicast through the same socket?
- Sending from the same UDP socket in multiple threads
- How to flush Input Buffer of an UDP Socket in C?
- How to find the socket buffer size of linux
- How do I get amount of queued data for UDP socket?
【问题讨论】:
-
为什么只有每 4 秒?为什么不让该线程坐在
select()呼叫中等待数据? -
@Collin 由于 UDP 不可靠,我们实现了以下机制。对于发送到客户端的每个 UDP 数据包,我都希望从客户端返回一个确认数据包(带有固定字符串的简单 UDP 数据包。)。如果我没有收到来自客户端的确认数据包,那么我将在 4 秒后再次发送数据包
-
好的,但是通过这种设置,服务器会认为数据包丢失了,即使它们没有丢失。在客户端读取套接字之后发送数据包会发生什么?使用网络计时,即使有响应,服务器也会认为从来没有响应。仍然没有理由不立即回应。尽管您可能会考虑使用 TCP 或类似的东西,而不是滚动您自己的可靠性:udt.sourceforge.net
-
您应该使用 select() 或使用阻塞模式并设置 4 秒 SO_TIMEOUT。这样,如果一个数据包在 4 秒内到达,您将立即读取它,而不是在睡眠中浪费时间。
-
@EJP 。您的评论很棒,它给了我清晰的想法,我会尝试以这种方式实施。我想给你的评论投票,但不幸的是我点击了两次,系统不允许我给你的评论投票:-(
标签: c++ linux sockets udp buffer