UDP数据传输比TCP慢

时间:2012-02-15 20:09:00

标签: c# .net sockets tcp udp

我目前正在C#/。Net4中编写原型应用程序,我需要传输未知数量的数据。数据从文本文件读入,然后序列化为字节数组。 现在我需要实现传输方法,UDP和TCP。两种方式的传输都运行良好,但我有一些与UDP斗争。我认为使用UDP的传输必须比使用TCP快得多,但实际上我的测试证明UDP传输比使用TCP慢大约7到8倍。 我用12兆字节的文件测试了传输,TCP传输大约需要1秒,而UDP传输大约需要7秒。 在应用程序中,我使用简单的套接字来传输数据。由于UDP每个消息只允许最大65535kb,我将序列化文件的字节数组分成几个部分,其中每个部分都具有socker SendBufferSize的大小,然后我使用Socket.Send()方法调用传输每个部分。

以下是发件人部分的代码。

while (startOffset < data.Length)
{
    if ((startOffset + payloadSize) > data.Length)
    {
        payloadSize = data.Length - startOffset;
    }
    byte[] subMessageBytes = new byte[payloadSize + 16];
    byte[] messagePrefix = new UdpMessagePrefix(data.Length, payloadSize, messageCount, messageId).ToByteArray();
    Buffer.BlockCopy(messagePrefix, 0, subMessageBytes, 0, 16);
    Buffer.BlockCopy(data, startOffset, subMessageBytes, messageOffset, payloadSize);
    messageId++;
    startOffset += payloadSize;
    udpClient.Send(subMessageBytes, subMessageBytes.Length);
    messages.Add(subMessageBytes);
}

此代码只是将要发送的下一部分复制到一个字节数组中,然后在套接字上调用send方法。我的第一个猜测是,字节数组的拆分/复制会降低性能,但我隔离并测试了拆分代码,拆分只需几毫秒,因此不会导致问题。

int receivedMessageCount = 1;
Dictionary<int, byte[]> receivedMessages = new Dictionary<int, byte[]>();
while (receivedMessageCount != totalMessageCount)
{
    byte[] data = udpClient.Receive(ref remoteIpEndPoint);
    UdpMessagePrefix p = UdpMessagePrefix.FromByteArray(data);
    receivedMessages.Add(p.MessageId, data);
    //Console.WriteLine("Received packet: " + receivedMessageCount + " (ID: " + p.MessageId + ")");
    receivedMessageCount++;
    //Console.WriteLine("ReceivedMessageCount: " + receivedMessageCount);
}
Console.WriteLine("Done...");
return receivedMessages;

这是我收到UDP消息的服务器端代码。每条消息都有一些字节作为前缀,其中存储了消息总数和大小。所以我只是在循环中调用socket.Receive,直到我收到前缀中指定的消息量。

我的假设是,我可能已经实现了UDP传输代码不够“有效”......也许你们其中一个人已经在代码片段中看到问题或者有任何其他建议或提示我为什么我的UDP传输比TCP慢。

提前感谢!

2 个答案:

答案 0 :(得分:3)

虽然UDP数据报大小可以达到64K,但实际的有线帧通常是1500字节(正常的以太网MTU)。这也必须适合最小20字节的IP头和8字节的UDP头,为您留下1472字节的可用有效载荷。

您所看到的是您的操作系统网络堆栈fragmenting发送方的UDP数据报,然后重新组装接收方的结果。这需要时间,因此需要你的结果。

另一方面,TCP会自行打包并尝试查找path MTU,因此在这种情况下效率更高。

将数据块限制为1472字节并再次测量。

答案 1 :(得分:0)

我认为您应该在测试期间测量CPU使用率和网络吞吐量。

如果CPU挂起,这就是您的问题:打开探查器。

如果网络(电缆)挂起,则这是一类不同的问题。我不知道该怎么办; - )

如果两者都没有挂钩,请运行一个探查器,看看大多数挂钟时间花在哪里。必须有一些等待。

如果你没有分析器,只需在调试器中点击10次,看看它最常停止的位置。

编辑:我对您的测量的回应:我们知道99%的执行时间都花在接收数据上。但我们还不知道CPU是否正忙。查看任务管理器并查看哪个进程正忙。

我的猜测是系统进程。这是Windows内核,可能是它的UDP组件。

这可能与数据包碎片有关。 IP数据包具有一定的最大大小,如1472字节。您的UDP数据包正在碎片化并在接收计算机上重新组装。我很惊讶,因为占用了大量的CPU时间。

尝试发送总大小为1000和1472的数据包(同时尝试!)并报告结果。