5

这可能是一个愚蠢的问题,但是由于我在这里对 UDP 比较陌生,所以……如果我有两个单独的字节数组,我需要接收方将它们作为一个大数组来获取,例如:

byte[] Array1 = {1,1,1}
byte[] Array2 = {2,2,2}

我是否可以避免创建缓冲区并将每个数组复制到其中,然后发送该缓冲区,如下所示:

byte[] Buffer= new byte[Array1.Length + Array2.Length];
Buffer.BlockCopy(Array1, 0, Buffer, 0, Array1.Length);
Buffer.BlockCopy(Array2, 0, Buffer, Array1.Length, Array2.Length);

udpClient.Send(Buffer, Buffer.Length);

因为如果两者都很大,并且数据速率很高,那么复制会占用很多系统资源......所以我可以以某种方式告诉 udpClient 我正在启动 UDP 分片,然后这样做:

udpClient.ImStartingOneBigDatagram();

udpClient.Send(Array1, Array1.Length);
udpClient.Send(Array2, Array2.Length);

udpClient.ThatsAllFolks();

并确保接收方将获得:

byte[] recv = {1,1,1,2,2,2}

我为此使用 C#,我不需要使用UdpClient,我只是在说明我的观点。

4

2 回答 2

2

是的,您可以将任何数据块分成两部分并将其作为两个单独的 UDP 数据包发送出去。但是,UDP 不保证交付,因此其中一件可能会在运输过程中丢失。如果收件人只收到一半的消息,你会怎么做?显然,把它扔掉,但使用 UDP 时要记住一些事情。

因此,要回答您问题的最后一部分“并确保接收方会得到……”,答案是否定的。您正在使用 UDP,因此您不能确定接收方会得到什么。

如果您想为了方便而不是出于网络数据包大小问题将发送分成多个块,您当然可以编写自己的包装类,它位于 UDPclient 之上并通过 Send 方法调用接受多个数据块,并且只发送当您在包装类上调用 .ThatsAllFolks 时,所有数据都会发送到 udpclient.Send()。但这不会减少内存开销,因为包装器必须在大发送之前将数据累积在内存中。这个包装器只是为您的客户端代码提供美观的便利。

于 2011-06-30T17:40:09.113 回答
2

使用相当于 Win32 API 的WSASendMsg

public int Send(
    IList<ArraySegment<byte>> buffers,
    SocketFlags socketFlags,
    out SocketError errorCode
)

http://msdn.microsoft.com/en-us/library/ms145161.aspx

但归根结底,这是过早的优化,如果您执行一些测试,您会发现要使用 I/O 分散收集数组,您至少需要 9KB 的数据才能获得性能提升。对于小缓冲区,即小于页面大小(x86 上为 4KB),在传递给套接字 API 之前自己构建一个连续缓冲区会更快。

于 2011-07-01T14:42:03.860 回答