Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can you maximize the throughput on a single TCP socket?
    primarykey
    data
    text
    <p>I am trying to get the standard example "echo" client/server application to run as quickly as possible and I am sure that the network is a limiting factor. I have a 1 gigabit network card and when I use resource monitor I am only getting 7 megabit out of the client.</p> <p>I understand the basics of sockets, message framing and length indicators, receiving all bytes indicated by the length indicator. Keep alive packets, half open connections etc.</p> <p>I started out using stock standard socket operations and then switched to using async. (I didn't change the send to async because someone [who seemed knowledgeable said it shouldn't have any impact]) I have the exact same performance and I can only think that all the material was assuming that I some other work that could be done on the same thread. But in my quick test I had dedicated 1 thread to conterminously spin in a loop sending and another completely different thread to receive. </p> <p>I have tried everything and am completely lost as to where I can get more performance. I used IPerf and that reported back speeds of 1 gigabit per second and resource monitor also showed that to be chewing up the bandwidth.</p> <p>Even if someone can maybe point me in the direction of a more complete example. Most of the ones I have come across are trivial or incomplete.</p> <p>Here is the general code.</p> <pre><code>class Program { private static Socket sock; private static BlockingCollection&lt;string&gt; queue; private static int bytesReceived; private static byte[] dataBuffer; private static readonly byte[] lengthBuffer = new byte[4]; private static byte[] PrependLengthIndicator(byte[] data) { return BitConverter.GetBytes(data.Length).Concat(data).ToArray(); } private static void Receive() { if (dataBuffer == null) { sock.BeginReceive(lengthBuffer, 0, 4, SocketFlags.None, ReceiveCallback, null); } else { sock.BeginReceive(dataBuffer, 0, bytesReceived, SocketFlags.None, ReceiveCallback, null); } } private static void ReceiveCallback(IAsyncResult ar) { bytesReceived += sock.EndReceive(ar); if (dataBuffer == null) { // Currently receiving length indicator if (bytesReceived &gt;= 4) { var length = BitConverter.ToInt32(lengthBuffer, 0); dataBuffer = new byte[length]; bytesReceived = 0; } } else { if (bytesReceived == dataBuffer.Length) { // Finished reading var request = Encoding.ASCII.GetString(dataBuffer); dataBuffer = null; bytesReceived = 0; queue.Add(request); } } ContinueReading(); } private static void ContinueReading() { // Read into the appropriate buffer: length or data if (dataBuffer != null) { sock.BeginReceive(dataBuffer, bytesReceived, dataBuffer.Length - bytesReceived, SocketFlags.None, ReceiveCallback, null); } else { sock.BeginReceive(lengthBuffer, bytesReceived, lengthBuffer.Length - bytesReceived, SocketFlags.None, ReceiveCallback, null); } } } </code></pre> <p>Here is the server portion:</p> <pre><code>static void Main(string[] args) { var listenSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listenSock.Bind(new IPEndPoint(IPAddress.Parse(ConfigurationManager.AppSettings["LocalIp"]), 3333)); listenSock.Listen(10); Console.WriteLine("Server started..."); sock = listenSock.Accept(); Console.WriteLine("Connection accepted."); queue = new BlockingCollection&lt;string&gt;(); Receive(); var count = 0; var sender = new Thread(() =&gt; { while (true) { var bar = queue.Take() + "Resp"; count++; var resp = Encoding.ASCII.GetBytes(bar); var toSend = PrependLengthIndicator(resp); if (count % 10000 == 0) { Console.WriteLine(bar); } sock.Send(toSend); } }); sender.Start(); } </code></pre> <p>Here is the client portion:</p> <pre><code>static void Main(string[] args) { sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Console.WriteLine("Connecting..."); sock.Connect(IPAddress.Parse(ConfigurationManager.AppSettings["EndPointIp"]), 3333); Console.WriteLine("Connected."); Receive(); var count = 0; while(true) { count++; var foo = "Echo-" + count; var data = Encoding.ASCII.GetBytes(foo); var toSend = PrependLengthIndicator(data); sock.Send(toSend); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload