Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send large data using C# UdpClient?

Tags:

c#

udp

I'm trying to send a large amount of data (more than 50 MB) using C# UdpClient.

So at first I split the data into 65507 byte blocks and send them in a loop.

for(int i = 0; i < packetCount; i++)
   myUdpClient.Send(blocks[i], block[i].Length, remoteEndPoint);

My problem is that only the first packets can be received. During sending the first packet the networkload increases rapidly to 100%, and then the other packets cannot be received.

I want to get as much data throughput as possible.

I'm sorry for my English! Thanks for your help in advance.

like image 411
raisyn Avatar asked Feb 23 '10 15:02

raisyn


3 Answers

I don't know about .Net implementation specifically, it might be buffering your data, but UDP datagram is normally limited by the link MTU, which is 1500 on normal ethernet (subtract 20 bytes for IP header and 8 bytes of UDP header.)

UDP is explicitly allowed to drop and reorder the datagrams, and there's no flow control as in TCP.

Exceeding the socket send buffer on the sender side will have the network stack ignore following send attempts until the buffer space is available again (you need to check the return value of the send() for that.)

Edit:

I would strongly recommend going with TCP for large file transfers. TCP gives you sequencing (you don't have to keep track of dropped and re-ordered packets.) It has advanced flow control (so fast sender does not overwhelm a slow receiver.) It also does Path MTU discovery (i.e. finds out optimal data packetization and avoids IP fragmentation.) Otherwise you would have to re-implement most of these features yourself.

like image 152
Nikolai Fetissov Avatar answered Oct 04 '22 22:10

Nikolai Fetissov


For all those people saying to use TCP....are foolishly wrong. Although TCP is reliable and the window maintained by the kernel it's fairly "set and forget" protocol, but when it comes to the guy wanting to use 100% of his throughput, TCP will not do (it throttles too hard, and the wait for an ACK automatically puts at least 50% trashed because of the RTT).

To the original question, you are sending UDP packets nonstop in that for-loop, the window fills up and then any new data is dropped immediately and doesn't even attempt to go on the line. You are also splitting your data too large. I would recommend building your own throttle mechanism that starts off with 2k segments per second, and slowly ramps up. Each "segment" contains a SEQ (sequence identifier for acknowledgements or ACK) and OFF (offset inside the file for this data set). As the data is being tagged, let the server keep track of these tags. When the other side gets them, it stores the SEQ numbers in an ACK list, and any missing SEQ numbers are placed into a NACK timer list, when the timer runs out (if they haven't been received) it moves to a NACK list. The receiver should send 5 or so ACKs from the ACK list along with up to 5 NACKs in a single transmission every couple seconds or so. If the sender receives these messages and there are any NACKs, it should immediately throttle down and resend the missing fragment before continuing. The data that is ACKed can be freed from memory.

Good luck!

like image 24
sabriath Avatar answered Oct 04 '22 23:10

sabriath


I hate to say it but you need to sleep the thread. You are overloading your throughput. UDP is not very good for lossless data transfer. UDP is for when you don't mind dropping some packets.

like image 39
msp Avatar answered Oct 04 '22 21:10

msp