2

我遇到了 C# 启动时间慢导致 UDP 数据包最初丢弃的问题。下面是我为减轻这种启动延迟所做的工作。我基本上在前两个数据包传输之间额外等待了 10 毫秒。这至少在我的机器上修复了初始下降。我担心的是较慢的机器可能需要比这更长的延迟。

private void FlushPacketsToNetwork()
{
    MemoryStream packetStream = new MemoryStream();

    while (packetQ.Count != 0)
    {
        byte[] packetBytes = packetQ.Dequeue().ToArray();
        packetStream.Write(packetBytes, 0, packetBytes.Length);
    }

    byte[] txArray = packetStream.ToArray();
    udpSocket.Send(txArray);

    txCount++;

    ExecuteStartupDelay();
}

// socket takes too long to transmit unless I give it some time to "warm up"
private void ExecuteStartupDelay()
{
    if (txCount < 3)
    {
        timer.SpinWait(10e-3);
    }
}

所以,我想知道有没有更好的方法让 C# 完全加载它的所有依赖项?我真的不介意完全加载是否需要几秒钟。我只是不想在 C# 准备好全速之前进行任何高带宽传输。

其他相关细节

这是一个控制台应用程序,网络传输是从一个单独的线程运行的,主线程只是等待按键来终止网络传输。

在该Program.Main方法中,我尝试通过使用合理的最高优先级从我的应用程序中获得最高性能:

public static void Main(string[] args)
{
    Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
    ...
    Thread workerThread = new Thread(new ThreadStart(worker.Run));
    workerThread.Priority = ThreadPriority.Highest;
    workerThread.Start();
    ...
    Console.WriteLine("Press any key to stop the stream...");
    WaitForKeyPress();

    worker.RequestStop = true;
    workerThread.Join();

此外,我当前使用的套接字设置如下所示:

udpSocket = new Socket(targetEndPoint.Address.AddressFamily,
                       SocketType.Dgram,
                       ProtocolType.Udp);
udpSocket.Ttl = ttl;
udpSocket.SendBufferSize = 1024 * 1024;
udpSocket.Blocking = true;

udpSocket.Connect(targetEndPoint);

默认值SendBufferSize是 8192,所以我继续将它移到了兆字节,但这个设置似乎对一开始丢弃的数据包没有任何影响。

4

1 回答 1

0

从评论中我了解到 TCP 不是你的选择(因为传输中的固有延迟),你也不想因为另一端没有完全加载而丢失数据包。

因此,您实际上需要以更健壮和轻量级的方式实现 TCP(重传)中存在的一些功能。我还假设您可以控制接收方。

我建议您发送一些预定数量的数据包。然后等待确认。例如,每个数据包都可以有一个不断增长的 id。每 N 个数据包,接收应用程序将最后收到的数据包的数量发送给发送者。收到此号码后,发送方将知道是否需要重复最后 N 个数据包。

这种方法不会对您的带宽造成太大影响,并且您将获得有关接收数据的某种信息(尽管不能保证)。

否则最好切换到 TCP。顺便说一句,您尝试过使用 TCP 吗?您的带宽因此受到了多大的伤害?

于 2012-05-29T18:07:07.800 回答