views:

517

answers:

4

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 firsr 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.

A: 

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.

msp
In addition to dropping some packets, UDP doesn't even guarantee that they will be received in the original order, which might also be a problem.
Lukas Pokorny
i usually have up to 10 udp-packet depending on each other... so if one packets gets lost i drop the other 9 packets as well, it isn't a problem if packets will be lost. This is the reason why I don't wanted to use tcp... I also thought with UDP I get better network throughput.
youllknow
+3  A: 

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.

Nikolai N Fetissov
the packet size of 65507 works fine in my LAN, the send() call always return 65507
youllknow
So what the receiver gets for the first 'packet'? 65507 bytes?
Nikolai N Fetissov
yes, he receive the whole 65507 byte at once
youllknow
Do you see IP fragments flowing on the wire? That's what that CPU spike is - fragmenting the 64K datagram into MTU-size packets.
Nikolai N Fetissov
I'm sorry, I can't understand. Please post the last message in more simple English! Thanks!
youllknow
The TCP/IP stack has to fragment the 64KB of data you give it. That shows as CPU/network load increase.
Nikolai N Fetissov
Why do you think the data must be fragmented... udp support packets up to 64KB
youllknow
But ethernet doesn't. The MTU is 1500 bytes (unless you use jumbo frames on a gigabit link, which still gives you around 9000,) so the sending machine has to split the 64KB chunk into smaller pieces. You can easily confirm that with Wireshark or whatever Microsoft has for network sniffer.
Nikolai N Fetissov
so the size for the data to use is 1472 bytes?
youllknow
That's maximum that fits into single IP packet. Things like PPPoE, or other tunneling protocols, might shave off more bytes. Path MTU is the minimum of all the links the packet has to traverse. This is why UDP protocols like DNS for example set upper packet size limit (DNS switches to TCP after 512 bytes.)
Nikolai N Fetissov
A: 

Reliably - no, you won't do it with UDP.

As far as I understand, this makes sense for sending to multiple computers at a time (broadcasting).

In this case,

  • establish a TCP connection with each of them,
  • split the data into blocks,
  • give each block an ID,
  • send list of IDs to each computer with TCP connection,
  • broadcast data with UDP,
  • inform clients (via TCP) that data transmission is over,
  • than clients should ask to resend the dropped packets
modosansreves
A: 

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!

sabriath