我应该怎么知道UDP编程?

时间:2009-04-28 17:40:13

标签: c++ sockets udp

我不是指如何连接到套接字。我应该了解UDP编程?

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

我真的需要知道什么?

12 个答案:

答案 0 :(得分:19)

  

“我应该假设我发送200bytes i   可能分别得到120和60字节?“

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

  

“我应该担心另一个人   连接发送给我的坏数据   同一个港口?“

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

  

如果数据通常不会到达   我可能(通常)看不到数据   为(250毫秒?1秒?1.75秒?)

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

答案 1 :(得分:9)

  

我应该担心另一个人   连接发送给我的坏数据   同一个港口?

是的,你应该担心。任何应用程序都可以随时将数据发送到您的开放UDP端口。 UDP的一个重要用途是多对一样式通信,您可以使用在recvfrom期间传回的地址与单个端口上的多个对等体进行多路复用,以区分对等体。

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

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

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

答案 2 :(得分:8)

您的信息包可能无法到达。

您的数据包可能会两次或更频繁地到达那里。

您的数据包可能没有整理。

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

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

答案 3 :(得分:6)

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

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

没有拥塞控制,所以你可能希望考虑一下,如果你打算用很多UDP数据包堵塞管道。

答案 4 :(得分:4)

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

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

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

长距离的延迟可能非常大。如果你想重新传输数据,我会使用当前连接的5到10倍的年龄延迟时间。 (您可以通过发送和接收一些数据包来衡量延迟。)

希望这会有所帮助。

答案 5 :(得分: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/

答案 6 :(得分:3)

尝试使用UDP时要知道的最重要的事情是:

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

如果您正在处理一个应用程序,其中100%的数据需要可靠地到达以提供功能,请使用TCP。如果您正在处理允许某些丢失的应用程序(流媒体等),那么请选择UDP,但不要指望所有内容都从一个管道传输到另一个管道。

答案 7 :(得分:2)

除了don.neufeld建议使用TCP。

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

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

答案 8 :(得分:2)

查看适用于UDP与TCP的应用程序之间的区别的一种方法是,当数据传递“迟到总比没有好”时,TCP是好的,当数据传递“永远不会迟到”时,UDP是好的。

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

答案 9 :(得分:1)

并且不要假设如果你发送一个数据包它就到了那里。

答案 10 :(得分:1)

如果某个路由器在此过程中存在数据包大小限制,您的UDP数据包可能会被静默截断为该数量。

答案 11 :(得分:0)

两件事:

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

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