Thread: Gigabit TCP Transfer

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    244

    Gigabit TCP Transfer

    Hello,

    I'm trying to achieve gigabit file transfer in c#. It is a speed test, so there is a packet of bytes, which is send out until the speed test is done.

    Code:
    					while (!Stopped)
    					{
    						stream.Write(data, 0, 524288);
    						transferred += data.Length;
    						[...]
    					}
    The point is that I'm reaching like 500 MBit/s, not at all gigabit. Let alone the CPU usage is extremely high (about 70%)

    The question here is: How can I minimize the CPU usage and how can I achieve maximum data throughput?

  2. #2
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    Well you could add at the top of your while loop...

    Code:
    Thread.Sleep(25);
    That should take care of your CPU usage issue, however, it won't help in aspiring for higher throughput rates.

  3. #3
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    Well, it would lower the CPU usage, but make the test results useless.. any other suggestions?

  4. #4
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    You could reduce the size of the packets you are sending so that you're not forcing the CPU to fragment the data before it is sent. The maximum TCP payload size for a packet is a little over 1400 bytes, so I would just send packets of 1400 to be sure.

    Also, make sure you are including the TCP and Ethernet header data when you perform your calculations.

    EDIT: Keep in mind that when you use TCP, there is the additional overhead of acknowledgements and resent packets that would not be present in your calculations.
    Last edited by bithub; 08-22-2011 at 11:31 AM.
    bit∙hub [bit-huhb] n. A source and destination for information.

  5. #5
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    Uisng 1400 bytes, it is far slower (say 5 MB/s). With 512 KB packets the speed is about 60 MB/s.
    the more data I send, the faster it gets... Don't know why.

    This is the other side, reading the packets:
    Code:
    private void ClientThread(TcpClient client)
    		{
    			try
    			{
    				NetworkStream stream = client.GetStream();
    				BinaryReader bin = new BinaryReader(stream);
    				byte[] buffer = new byte[bin.ReadInt32()];                         // read the size of the packets
    				while (true)
    				{
    					stream.Read(buffer, 0, buffer.Length);
    				}
    			}
    			catch { }
    		}
    And yes, I know that TCP has an overhead of about 20%

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Is the machine you're dumping all this data on just as fast as this one? It's all very well having a super highway, but if it ends in a dirt track, you're stuck all the same.

    Bear in mind that TCP connections are reliable, so there is a certain amount of traffic to 'ack' the transmission, wait for packet retransmission, and buffering to limit the number of un-acked packets.

    You would get higher throughput with UDP.

    Further, the OS is unlikely to allow a single user land process to saturate the link, when it needs a certain amount of bandwidth for it's own use, and to satisfy Quality of service - Wikipedia, the free encyclopedia levels for other active links.

    Do you have a firewall that scans all outbound traffic?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    Both machines have about the same performance. The firewall doesn't seem to slow down anything (same speed when turned off).
    I will try it with UDP now.

  8. #8
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    UDP isn't much faster, because of the datagram size. When I'm sending 1400 bytes or 10 KB via UDP, the speed is between 5 MB/s and 30 MB/s. When using TCP and 1400 bytes it is also 5 MB/s. But using TCP and 512 KB speeds up to 60 MB/s. It seems more like there is a problem with the packet size or the way I'm sending.

    Here's the source: http://xload.dev-ch.de/f690bc45828e7...1.0.0b-src.zip
    If you could look into it, I would be happy
    Maybe you'll see the mistake I'm making right away.

  9. #9
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    Your best bet for responses is to actually post the relevant code here with code tags. If you aren't sure what parts of the code are in question, then either post the whole thing with tags or attach the actual files. Very few people are going to download a zip file from someone that do not know.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  10. #10
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    Ok, good point. So here is the source code of the most important parts:

    This happens, when a client joins the server. Here, the data is read until the connection is closed.
    Code:
    private void ClientThread(TcpClient client)
    		{
    			try
    			{
    				NetworkStream stream = client.GetStream();
    				BinaryReader bin = new BinaryReader(stream);
    				byte[] buffer = new byte[bin.ReadInt32()];
    				while (true)
    				{
    					stream.Read(buffer, 0, buffer.Length);
    				}
    			}
    			catch { }
    		}
    This is the connection code for a TCP client:
    Code:
    public TcpClient Connect(string ip)
    		{
    			try
    			{
    				TcpClient client = new TcpClient(ip, Port);
    				client.NoDelay = true;
    				return client;
    			}
    			catch
    			{
    				return null;
    			}
    		}
    and this is the code, which sends tcp packets:
    Code:
    private void btnRun_Click(object sender, EventArgs e)
    		{
    			btnStop.Text = "Stop";
    			Stopped = false;
    			lblSpeed.Text = "0 Bytes/s";
    			lblSpeedBit.Text = "0 Bits/s";
    			netGauge.KBitsPerSecond = 0;
    			netGauge.Invalidate();
    			lblConnectionLost.Visible = false;
    			try
    			{
    				if (lstComputers.SelectedItems.Count == 1)
    				{
    					tabMain.SelectedIndex = 2;
    					btnNext.Visible = false;
    					btnRun.Visible = false;
    					btnStop.Visible = true;
    					lblConnectedTo.Text = lstComputers.SelectedItems[0].Text;
    					lblConnectedIP.Text = (string)lstComputers.SelectedItems[0].Tag;
    
    					TcpClient client = Analyzer.Connect(lblConnectedIP.Text);
    					NetworkStream stream = client.GetStream();
    					BinaryWriter bin = new BinaryWriter(stream);
    					int len = (int)edtPacketSize.Value;
    					bin.Write(len);
    					byte[] data = new byte[len];
    					if (chkRandomData.Checked)
    					{
    						RandomNumberGenerator.Create().GetBytes(data);
    					}
    
    					long transferred = 0, transferredthissecond = 0;
    					DateTime start = DateTime.Now, lastrefresh = DateTime.Now, lastmeasured = DateTime.Now;
    
    					while (!Stopped)
    					{
    						stream.Write(data, 0, data.Length);
    						transferred += data.Length;
    						transferredthissecond += data.Length;
    						if ((DateTime.Now - lastmeasured).TotalMilliseconds > 500)
    						{
    							lastmeasured = DateTime.Now;
    							transferredthissecond *= 2;
    							lblSpeed.Text = GetSizeName(transferredthissecond) + "/s";
    							lblSpeedBit.Text = GetBitSizeName(transferredthissecond) + "/s";
    							netGauge.KBitsPerSecond = (int)(transferredthissecond * 8 / 1000);
    							netGauge.Invalidate();
    							transferredthissecond = 0;
    						}
    
    						lblTransferred.Text = GetSizeName(transferred);
    						if ((DateTime.Now - lastrefresh).TotalMilliseconds > 25)
    						{
    							TimeSpan timespan = DateTime.Now - start;
    							lblTimeElapsed.Text = (timespan).ToString().PadRight(11).Substring(0, 11);
    							int avg = (int)(transferred / timespan.TotalSeconds);
    							lblAverageSpeed.Text = GetSizeName(avg) + "/s - " + GetBitSizeName(avg) + "/s";
    							Application.DoEvents();
    							lastrefresh = DateTime.Now;
    						}
    					}
    					client.Close();
    				}
    			}
    			catch
    			{
    				lblConnectionLost.Visible = true;
    			}
    			btnStop.Text = "<< First";
    		}

  11. #11
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    a standard 33MHz/32-bit PCI bus can only move about a gigabit per second of data, so unless you're using a 64-bit or 66MHz PCI or PCI-e bus, there's a good chance that your machine just doesn't have the bus bandwidth to push that kind of data, when everything else is also going on inside the machine. a lot of computers/motherboards are still made with the ethernet port connected to a PCI bus instead of a PCI-e bus, so this is a real possibility.

    on another note, gigabit ethernet supports jumbo frames, up to (and maybe over) 16k. if both machines and your switch are set to support jumbo frames (9000 bytes is usually a good number for a few reasons) you may be able to get higher transfer rates, assuming you also have machines that can handle data at that rate.

  12. #12
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    The transfer rates are slow, when using such small packet sizes. For example 1400 bytes packet size slows the speed down to 5 MB/s. It seems to be some kind of coding issue...
    Btw: you seem to have pretty well knowledge of TCP and networking

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Transfer function in C ? How to do it ?
    By integralx2 in forum C Programming
    Replies: 2
    Last Post: 01-09-2011, 08:49 PM
  2. File Transfer?
    By illiterate in forum C++ Programming
    Replies: 3
    Last Post: 07-23-2010, 04:35 AM
  3. transfer
    By C-Compiler in forum Windows Programming
    Replies: 6
    Last Post: 11-23-2008, 08:07 PM
  4. File Transfer
    By rogue in forum C++ Programming
    Replies: 6
    Last Post: 01-25-2006, 07:57 AM
  5. File transfer
    By scrapedbr in forum C Programming
    Replies: 1
    Last Post: 05-27-2004, 12:46 PM