【问题标题】:Are UDP packets ephemeral or will the server keep received packets until read?UDP数据包是短暂的还是服务器会保留收到的数据包直到读取?
【发布时间】:2014-05-02 11:04:37
【问题描述】:

我有一个在我的数据库上运行的后端进程。这是在单独的计算机上使用的,因此前端可以创造奇迹(至少在速度方面)。该后端进程创建一个 UDP 服务器并在其上侦听数据包。

在前端计算机上,我从服务器创建子进程。每个孩子都可能在数据库中创建需要后端做更多工作的数据。为了让后端知道,我使用 UDP 客户端连接发送 PING。

  Front End / Backend Setup                        Processing

+-------+         +---------+                     +----------+
|       |         |         |                     | Internet |
| Front |  PING   | Backend |                     | Client   |
|  End  |-------->|         |                     +----------+
|       |         |         |              HTTP Request | 
+-------+         +---------+                           v
    ^                  ^                          +----------+
    |                  |                          | FrontEnd |--------+
    |                  |                          +----------+   PING |
    v                  v                  HTTP Response |             v
+---------------------------+                           v         +---------+
|                           |                     +----------+    | Backend |
|    Cassandra  Database    |                     | Internet |    +---------+
|                           |                     | Client   |
+---------------------------+                     +----------+

如果没有 PING,后端将结束其工作并进入休眠状态,直到下一次 PING 将其唤醒。虽然有故障保护,但我设置了 5 分钟的超时时间,所以无论如何后端都会偶尔唤醒一次。

我的问题是关于 UDP 堆栈,我知道它是一个 FIFO,但我想知道两个参数:

  1. 在 FIFO 变满之前我可以接收多少个 PING?

  2. 如果我没有尽快阅读 PING,我是否会收到 PING 并丢失它?

这些问题的答案可以帮助我调整后端服务器当前的等待循环。到目前为止,我假设 FIFO 有一个限制,并且我可能会丢失一些数据包,但我还没有实现允许数据包消失的方法(即有人发送 PING,但后端在再次检查 UDP 堆栈之前需要很长时间因此网络决定该数据包现在已超时并将其从我脚下删除。)


更新:我添加了一个简单的处理来显示什么时候会发生什么(从上到下是基于时间的)

【问题讨论】:

  • UDP 数据包不能保证被接收。为什么不对服务器进行编程以发送返回数据包,这样至少您可以看到收到了 ping?如果做不到这一点,请经常发送 ping,以便统计上服务器极不可能进入休眠状态。
  • 前端必须尽可能快地运行。它正在响应一个 HTTP 请求,所以我不希望它等待任何东西。因为我想会有足够的前端 ping,所以你提到的应该由系统的本质来处理。我想知道是否可以撤回数据包。在一个相当慢的系统上,后端可能需要 5 分钟才能开始执行本可以在几秒钟内完成的工作......
  • 您的后端系统应该立即确认收到的数据包。如果服务器响应数据包可能需要 5 分钟,您应该考虑某种形式的异步处理,例如 Node.JS 使用的。 5 分钟对于同步请求来说有点太长了。
  • 我希望在后端处理完新数据(数据库中的数据)时前端已经消失。后端的用途是进行前端可以跳过的处理,这样向客户端发送回复的速度要快得多。 5分钟。是一种安全防护,以防后端以某种方式错过所有 ping... 这将在本地网络环境中工作,所以我不希望在 5 分钟内丢失这么多 UDP 数据包。最终将成为唯一的行动手段。

标签: networking udp


【解决方案1】:

在 FIFO 满之前我可以接收多少 PING?

这取决于你的套接字接收缓冲区的大小。

如果我没有尽快阅读,我是否会收到 PING 并丢失它?

是和不是。已接收并适合套接字接收缓冲区的数据报保留在那里,直到它们被读取或套接字关闭。您可以在限制范围内调整套接字接收缓冲区的大小。但是,当套接字接收缓冲区已满时到达的数据报将被丢弃。

【讨论】:

  • 我认为正文中的第 (2) 点是标题中问题的重复。但这是个好消息。我以为会是这样,但真的找不到说得这么清楚的文档。
【解决方案2】:

您可以使用 sysctl 设置系统上的默认缓冲区大小,或使用带有 SO_RCVBUF 选项的 setsockopt 设置每个套接字。

int n = 512 * 1024; // 512K
if (setsockopt(my_socket, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) {
   perror("Failed to set buffer size, using default");
}

系统上还有一个您不能超过的最大值。在我的机器上,默认接收缓冲区大小为 208K,最大值为 4M:

# sysctl net.core.rmem_max
net.core.rmem_max = 4194304
# sysctl net.core.rmem_default
net.core.rmem_default = 212992

【讨论】:

    猜你喜欢
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 2017-08-18
    • 2012-02-09
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    相关资源
    最近更新 更多