简体   繁体   中英

Waiting for networking C# console application to fully start

I have run into an issue with the slow C# start-up time causing UDP packets to drop initially. Below, I is what I have done to mitigate this start-up delay. I essentially wait an additional 10ms between the first two packet transmissions. This fixes the initial drops at least on my machine. My concern is that a slower machine may need a longer delay than this.

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);
    }
}

So, I am wondering is there a better approach to let C# fully load all of its dependencies? I really don't mind if it takes several seconds to completely load; I just do not want to do any high bandwidth transmissions until C# is ready for full speed.

Additional relevant details

This is a console application, the network transmission is run from a separate thread, and the main thread just waits for a key press to terminate the network transmitter.

In the Program.Main method I have tried to get the most performance from my application by using the highest priorities reasonable:

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();

Also, the socket settings I am currently using are shown below:

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

udpSocket.Connect(targetEndPoint);

The default SendBufferSize is 8192, so I went ahead and moved it up to a megabyte, but this setting did not seem to have any affect on the dropped packets at the beginning.

From the comments I learned that TCP is not an option for you (because of inherent delays in transmission), also you do not want to loose packets due to other side being not fully loaded.

So you actually need to implement some features present in TCP (retransmission) but in more robust and lightweight fashion. I also assume that you are in control of the receiving side.

I propose that you send some predetermined number of packets. And then wait for confirmation. For instance, every packet can have an id that constantly grows. Every N packets, receiving application sends the number of last received packet to the sender. After receiving this number sender will know if it is necessary to repeat last N packets.

This approach should not hurt your bandwidth very much and you will get some sort of information about received data (although not guaranteed).

Otherwise it is best to switch to TCP. By the way did you try using TCP? How much your bandwidth hurts because of it?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM