UdpClient.Send 方法和 UdpClient.Client.Send 方法的区别

Posted

技术标签:

【中文标题】UdpClient.Send 方法和 UdpClient.Client.Send 方法的区别【英文标题】:Difference between UdpClient.Send method and UdpClient.Client.Send method 【发布时间】:2011-11-10 23:32:40 【问题描述】:

我可以使用 UdpClient.Send(byte array) 或 UdpClient.Client.Send(stream) 方法通过 udp 协议发送数据。两种方法都有效。唯一的区别是,在一种方法中我传递一个字节数组,而在另一种方法中我传递一个流。

快速示例:

UdpClient udpClient = new UdpClient(localEndPoint);
// I can eather send data as:
udpClient.Send(new byte[]  0, 1, 2 , 3);
udpClient.Client.Send(new byte[5]);

还有哪种方法可以确保我的数据在不丢失信息的情况下到达目的地?我已经读过 udp 协议不能确保所有字节都到达它的目的地,因此更适合流式传输视频、音频,但不适用于像我正在做的那样传输文件。我之所以使用 udp 而不是 tcp,是因为在恰好位于路由器后面的两个用户之间建立 tcp 连接非常复杂。我知道如果其中一位用户在他的路由器上启用端口转发是可能的。我设法通过所谓的 udp 打孔来发送数据。 udp 打孔使您能够在服务器的帮助下在路由器后面的两个用户之间建立连接。在这里解释它是如何工作的将会很长,如果你用谷歌搜索它,你可以找到很多信息。不管怎样,我只是想让你知道我为什么使用 udp 而不是 tcp。我现在不知道是否可以使用此协议发送文件以确保没有数据丢失。也许我必须创建一个算法。或者 UdpClient.Client.Send 方法可以确保接收到数据,而 UdpClient.Send 方法不能确保接收到数据。

【问题讨论】:

【参考方案1】:

UDP 不保证它们的数据传递或顺序。它只保证如果您成功接收数据包,则数据包是完整的。您需要通过您自己的实现使您的网络通信可靠。这两个函数应该没有任何区别。

UNIX Network Programming 有一个关于这个主题的章节。 (22.5 增加 UDP 应用程序的可靠性)。你也可以看看libginble,它支持NAT穿越功能(带STUN或中继)和通信的可靠性。

这篇文章Reliability and Flow Control 也可以帮助您了解一种可能的实现方式。祝你好运!

【讨论】:

【参考方案2】:

这两种方法没有区别,UdpClient 是一个 Socket 的包装器。 UdpClient.Client 只是让您直接访问 UdpClient 正在使用的 Socket。它们最终都通过套接字发送数据。

两者都不保证会收到所有数据。 UDP 不保证 1. 数据将被传递 2. 如果已传递,则将按顺序传递。如果你需要这两个(并且不能使用 TCP),你必须自己编写代码。

您可以使用的最简单的协议是为每个数据包添加一个序列。让服务器发送一个数据包并等待客户端收到它的响应,然后发送下一个数据包。顺序很重要,因为如果客户端对服务器的响应丢失,客户端可能会从服务器接收两次相同的数据包。

您的序列号可以是文件大小的当前位置(以字节为单位)——这就是 TCP 使用的。

我建议您阅读 TCP 协议,以便了解它用于处理可靠性的机制(请记住 TCP 和 UDP 都是基于 IP 构建的 - TCP 只是一个更强大(和复杂)的协议,因此您可以实现部分自己动手)

【讨论】:

我希望我可以使用 tcp。我无法在 nat 后面的两个用户之间建立 tcp 连接。通过在服务器的帮助下进行 udp 打孔,我已经能够使用 udp 做到这一点。也许我可以使用其他协议(如 ftp)进行打孔。我的意思是我想使用 udp 的原因是因为它是唯一使我能够在 nat 后面连接两个对等方而无需在路由器上启用端口转发的协议

以上是关于UdpClient.Send 方法和 UdpClient.Client.Send 方法的区别的主要内容,如果未能解决你的问题,请参考以下文章

ios 类方法和实例方法的区别

JAVA中构造方法和普通方法的区别

Javascript的私有变量和方法共有变量和方法以及特权方法构造器静态共有属性和静态共有方法

093 类和对象的绑定方法和非绑定方法

init()方法和构造方法的区别

Python中静态方法和类方法的区别