我并不是说如何连接套接字。关于UDP编程,我需要了解哪些内容?
- 我需要担心套接字中出现的坏数据吗?
- 如果我发送了200字节,我应该假设会分别收到120和60字节吗?
- 我是否需要担心另一个连接在同一端口上向我发送坏数据?
- 如果数据没有到达,通常我可能要等多长时间才能看到数据(250毫秒?1秒?1.75秒?)
我真正需要知道什么?
"如果我发送了200字节,我可能会分别收到120字节和60字节吗?"
当您发送UDP数据报时,读取的大小将等于写入的大小。这是因为UDP是一种数据报协议,而TCP是一种流协议。但是,在数据包可能被路由器分段或丢弃之前,您只能写入MTU的大小。对于一般互联网使用,安全的MTU大小是576字节,包括头。
"我应该担心另一个连接在同一端口上向我发送了错误的数据吗?"
您没有连接,只有端口。无论来自哪里,您都将接收到发送到该端口的任何数据。您需要确定它是否来自正确的地址。
如果数据通常不到达,我可能需要多长时间才能看到数据(250ms?1秒钟?1.75秒?)
数据可能永久丢失、延迟或乱序到达。如果这些问题中的任何一个困扰您,请使用TCP。在UDP之上编写可靠的协议非常复杂,并且几乎所有应用程序都没有必要这样做。
我应该担心另一个连接在同一端口上向我发送错误数据吗?
是的,您应该担心。任何应用程序都可以随时向您的开放UDP端口发送数据。 UDP的一个重要用途是多对一样式通信,您可以使用recvfrom
返回的地址来区分多个对等方之间的通信。
但是,如果您想避免这种情况,并且只接受来自单个对等方的数据包,则可以在UDP套接字上调用connect
。这会导致IP堆栈拒绝来自除您想要通信的主机:端口组合(套接字)之外的任何主机:端口组合的数据包。
在UDP套接字上调用connect
的第二个优点是,在许多操作系统中,它可以显著提高速度/延迟。当您在未连接的UDP套接字上调用sendto
时,操作系统实际上会暂时连接套接字,发送数据,然后断开套接字,从而增加了显着的开销。
使用已连接的UDP套接字的第三个优点是,它允许您将ICMP错误消息发送回您的应用程序,例如由于崩溃而导致的路由或主机未知。如果UDP套接字未连接,则操作系统将不知道从网络传递ICMP错误消息的位置,并会悄悄地丢弃它们,这可能会导致您的应用程序在等待来自崩溃主机的响应(或等待选择超时)时挂起。
您的数据包可能无法到达目的地。
您的数据包可能会被发送两次或多次。
您的数据包可能不会按顺序到达。
底层网络层对您的数据包大小有限制。数据包大小可能非常小(可能为576字节)。
这并不意味着“不要使用UDP”。但是,您应该注意以上所有内容,并考虑您可能想要采取哪些恢复选项。
我需要担心套接字中的错误数据吗?
是的。尽管UDP包含一个非常简单的校验和用于路由器等设备,但它并不是100%有效的。您可以添加自己的校验设备,但大多数情况下,当可靠性已经不是问题时,使用UDP,因此不符合规范的数据应该被丢弃。如果我发送200字节,我应该假设我会分别收到120和60字节吗?
不,UDP是直接数据写入和读取。但是,如果数据太大,一些路由器将会截断数据,您将永久失去部分数据。有人说大约576字节带头文件,我个人不会使用超过256字节(好的2的对数)。我应该担心另一个连接在同一端口上向我发送错误数据吗?
UDP侦听来自端口上任何计算机的任何数据,因此从这个意义上说是的。还要注意,UDP是原始格式,可以使用伪造的发送方,因此您应该使用某种“键”以便侦听器验证发送方是否与其IP地址匹配。如果数据没有到达,我通常可能多长时间看不到数据(250毫秒?1秒?1.75秒?)
通过UDP发送的数据通常是一次性的,因此如果您没有收到数据,则可以轻松忽略它。但是,有时您需要“半可靠”,但又不想使用TCP所使用的“有序可靠”,1秒是一个很好的掉落估计值。您可以对旋转的数据包进行编号并编写自己的ACK通信。当接收到数据包时,它记录编号并发送回位域,让发送方知道它接收了哪些数据包。您可以阅读这份未完成的文档以获取更多信息(尽管未完成,但仍提供有价值的信息): http://gafferongames.com/networking-for-game-programmers/在尝试使用UDP时需要知道的重要事情是:
你的数据包可能无法全部传输,这意味着可能会出现数据损坏。
如果你正在开发一个应用程序,其中100%的数据需要可靠地到达以提供功能,请使用TCP。如果你正在开发一个允许一些丢失的应用程序(如流媒体等),那么选择UDP,但不要期望所有数据从一个管道传输到另一个管道时都完好无损。
UDP和TCP适用的应用不同,可以这样理解:当数据传输“迟到总比不到好”时,TCP是很好的选择;而当数据传输“宁愿不到也不能迟到”时,UDP更为合适。
另一个方面是,大多数基于UDP的应用程序具有无状态、尽力而为的特点,这使得可扩展性更容易实现。此外,请注意UDP可以进行组播,而TCP不能。
不要假设你发送了一个数据包就一定能够到达目的地。