17

我不是说如何连接到套接字。关于 UDP 编程我应该知道什么?

  • 我需要担心套接字中的错误数据吗?
  • 我应该假设如果我发送 200 字节,我可能会分别得到 120 和 60 字节?
  • 我应该担心另一个连接在同一端口上向我发送错误数据吗?
  • 如果数据通常没有到达,我可以(通常)在多长时间内看不到数据(250 毫秒?1 秒?1.75 秒?)

我真正需要知道什么?

4

12 回答 12

19

“我应该假设如果我发送 200 字节,我可能会分别得到 120 和 60 字节?”

当您发送 UDP 数据报时,您的读取大小将等于您的写入大小。这是因为 UDP 是一种数据报协议,而不是 TCP 的协议。但是,在数据包可能被路由器分段或丢弃之前,您只能写入最大 MTU 大小的数据。对于一般互联网使用,安全 MTU 为 576 字节,包括标头。

“我应该担心另一个连接在同一个端口上向我发送坏数据吗?”

你没有连接,你有一个端口。无论数据来自何处,您都会收到发送到该端口的任何数据。由您决定它是否来自正确的地址。

如果数据通常没有到达,我可能(通常)在多长时间内(250 毫秒?1 秒?1.75 秒?)看不到数据

数据可能永远丢失,数据可能会延迟,数据可能会乱序到达。 如果这些事情中的任何一个困扰您,请使用 TCP。 在 UDP 之上编写可靠的协议是一项非常重要的任务,几乎所有应用程序都没有理由这样做。

于 2009-04-28T17:42:31.533 回答
9

我应该担心另一个连接在同一端口上向我发送错误数据吗?

是的,你应该担心它。任何应用程序都可以随时向您开放的 UDP 端口发送数据。UDP 的一大用途是多对一风格的通信,在这种通信中,您可以使用在单个端口上与多个对等方进行多路通信,使用在传输期间传回的地址recvfrom来区分对等方。

但是,如果您想避免这种情况并且只接受来自单个对等方的数据包,您实际上可以connect在您的 UDP 套接字上调用。这会导致 IP 堆栈拒绝来自任何主机:端口组合(套接字)的数据包,而不是您要与之交谈的数据包。

调用 UDP 套接字的第二个优点connect是,在许多操作系统中,它显着提高了速度/延迟。当您调用sendto未连接的 UDP 套接字时,操作系统实际上会临时连接套接字,发送您的数据,然后断开套接字,这会增加大量开销。

使用连接的 UDP 套接字的第三个优点是它允许您将 ICMP 错误消息接收回您的应用程序,例如由于崩溃而导致的路由或主机未知。如果未连接 UDP 套接字,操作系统将不知道将 ICMP 错误消息从网络传递到何处,并将静默丢弃它们,这可能会导致您的应用程序在等待崩溃主机的响应时挂起(或等待您的选择超时)。

于 2009-04-28T18:58:02.117 回答
8

您的数据包可能无法到达那里。

您的数据包可能会到达那里两次甚至更多次。

您的数据包可能不按顺序排列。

您对底层网络层施加的数据包有大小限制。数据包大小可能非常小(可能为576字节)。

这些都不是说“不要使用UDP”。但是,您应该了解以上所有内容,并考虑您可能想要采取的恢复选项。

于 2009-04-28T17:49:31.767 回答
6

碎片和重组发生在 IP 级别,因此您不必担心(维基百科)。(这意味着您不会收到拆分或截断的数据包)。

UDP 数据包具有数据和标头的校验和,因此不太可能接收到虚假数据,但有可能。丢失或重复的数据包也是可能的。无论如何,您都应该检查您的数据。

没有拥塞控制,因此如果您打算用大量 UDP 数据包堵塞管道,您可能希望考虑这一点。

于 2009-04-28T17:58:46.690 回答
4

UDP 是一种无连接协议。通过 UDP 发送数据可以到达接收方,但也可能在传输过程中丢失。UDP 非常适合广播和流式传输音频或视频(即在这些情况下丢弃的数据包永远不会成为问题。)因此,如果您需要确保数据到达另一端,请坚持使用 TCP。

UDP 的开销比 TCP 少,因此速度更快。(TCP 需要先建立连接,还要检查数据包是否有数据损坏,这需要时间。)

分段的 UDP 数据包(即大于约半 Kb 的数据包)可能会被路由器丢弃,因此在发送之前将您的数据分成小块。(在某些情况下,操作系统可以解决这个问题。)请注意,它总是一个可能会成功的数据包,也可能不会。一半数据包未处理。

长距离的延迟可能非常大。如果你想重新传输数据,我会选择当前连接上老化延迟时间的 5 到 10 倍。(您可以通过发送和接收几个数据包来测量延迟。)

希望这可以帮助。

于 2009-04-28T17:58:06.380 回答
4

我不会和其他回答这个问题的人一起效仿,他们似乎都将你推向 TCP,这根本不是为了游戏,除了登录/聊天信息。让我们按顺序进行:

我需要担心套接字中的错误数据吗?

是的。即使 UDP 包含一个非常简单的路由器校验和等,它也不是 100% 有效的。您可以添加自己的校验和设备,但大多数时候在可靠性已经不是问题的情况下使用 UDP,因此应该丢弃不符合要求的数据。

我应该假设如果我发送 200 字节,我可能会分别得到 120 和 60 字节?

不,UDP 是直接数据写入和读取。但是,如果数据太大,某些路由器会截断,您会永久丢失部分数据。有些人说大约 576 字节带有标题,我个人不会使用超过 256 字节(漂亮的圆形 log2 数)。

我应该担心另一个连接在同一端口上向我发送错误数据吗?

UDP 在端口上侦听来自任何计算机的任何数据,所以从这个意义上说是的。另请注意,UDP 是一种原始格式,原始格式可用于伪造发送者,因此您应该使用某种“密钥”,以便侦听器根据其 IP 验证发送者。

如果数据通常没有到达,我可以(通常)在多长时间内看不到数据(250 毫秒?1 秒?1.75 秒?)

在 UDP 上发送的数据通常是一次性的,所以如果你没有收到数据,那么它很容易被忽略......但是,有时你想要“半可靠”但你不想要像 TCP 使用的“有序可靠”, 1 秒是一个很好的下降估计。您可以在轮换中对数据包进行编号并编写自己的 ACK 通信。当接收到一个数据包时,它会记录数字并发送回一个位域,让发送者知道它收到了哪些数据包。您可以阅读此未完成的文档以获取更多信息(尽管未完成,但它仍然会产生有用的信息):

http://gafferongames.com/networking-for-game-programmers/

于 2009-12-18T14:06:01.720 回答
3

尝试使用 UDP 时要知道的一件大事是:

您的数据包可能不会全部通过线路,这意味着可能存在数据损坏。

如果您正在开发的应用程序需要 100% 的数据可靠地到达以提供功能,请使用 TCP。如果您正在开发允许一些丢失的应用程序(流媒体等),那么请使用 UDP,但不要指望一切都可以从一个管道完好无损地传输到另一个管道。

于 2009-04-28T17:44:25.617 回答
2

除了 don.neufeld 建议使用 TCP。

对于大多数应用程序,TCP 更容易实现。如果您需要在 TCP 流中维护数据包边界,一个好方法是在数据之前传输两个字节的标头来分隔消息。标头应包含消息长度。在接收端只需读取两个字节并评估值。然后等到你收到那么多字节。然后,您将获得一条完整的消息,并准备好接收下一个 2 字节标头。

这为您提供了 UDP 的一些好处,而没有丢失数据、无序数据包到达等的麻烦。

于 2009-04-28T18:09:23.047 回答
2

查看适用于 UDP 与 TCP 的应用程序之间差异的一种方法是,当数据传递“迟到总比不迟”时,TCP 是好的,而当数据传递“比迟到好”时,UDP 是好的。

另一方面是大多数基于 UDP 的应用程序的无状态、尽力而为的特性可以使可伸缩性更容易实现。另请注意,UDP 可以多播,而 TCP 不能。

于 2009-04-28T18:21:28.900 回答
1

并且不要假设如果您发送一个数据包,它就会到达那里。

于 2009-04-28T17:43:16.620 回答
1

如果沿途某些路由器施加了数据包大小限制,则您的 UDP 数据包可能会被静默截断为该大小。

于 2009-04-28T17:52:05.053 回答
0

两件事情:

1)您可能会或可能不会收到发送的内容

2) 无论您收到什么,都可能与发送时的顺序不同。

于 2009-04-28T18:07:10.447 回答