I have a network code to handle an arbitrary TCP connection.
Everything works as expected, but seems slow. When I was profiling the code, it seems to have spent a good 600 ms in NetworkStream.Read (), and I am wondering how to improve it. I was looking for buffer sizes and alternating between a massive buffer to read all the data in one go or a small one that should combine the data into a StringBuilder. The client I'm using is currently a web browser, but this code is generic and it may not be the HTTP data that is sent to it. Any ideas?
My code is:
public void StartListening() { try { lock (oSyncRoot) { oTCPListener = new TcpListener(oIPaddress, nPort); // fire up the server oTCPListener.Start(); // set listening bit bIsListening = true; } // Enter the listening loop. do { // Wait for connection TcpClient newClient = oTCPListener.AcceptTcpClient(); // queue a request to take care of the client oThreadPool.QueueUserWorkItem(new WaitCallback(ProcessConnection), newClient); } while (bIsListening); } catch (SocketException se) { Logger.Write(new TCPLogEntry("SocketException: " + se.ToString())); } finally { // shut it down StopListening(); } } private void ProcessConnection(object oClient) { TcpClient oTCPClient = (TcpClient)oClient; try { byte[] abBuffer = new byte[1024]; StringBuilder sbReceivedData = new StringBuilder(); using (NetworkStream oNetworkStream = oTCPClient.GetStream()) { // set initial read timeout to nInitialTimeoutMS to allow for connection oNetworkStream.ReadTimeout = nInitialTimeoutMS; int nBytesRead = 0; do { try { bool bDataAvailable = oNetworkStream.DataAvailable; while (!bDataAvailable) { Thread.Sleep(5); bDataAvailable = oNetworkStream.DataAvailable; } nBytesRead = oNetworkStream.Read(abBuffer, 0, abBuffer.Length); if (nBytesRead > 0) { // Translate data bytes to an ASCII string and append sbReceivedData.Append(Encoding.UTF8.GetString(abBuffer, 0, nBytesRead)); // decrease read timeout to nReadTimeoutMS second now that data is coming in oNetworkStream.ReadTimeout = nReadTimeoutMS; } } catch (IOException) { // read timed out, all data has been retrieved nBytesRead = 0; } } while (nBytesRead > 0); //send the data to the callback and get the response back byte[] abResponse = oClientHandlerDelegate(sbReceivedData.ToString(), oTCPClient); if (abResponse != null) { oNetworkStream.Write(abResponse, 0, abResponse.Length); oNetworkStream.Flush(); } } } catch (Exception e) { Logger.Write(new TCPLogEntry("Caught Exception " + e.StackTrace)); } finally { // stop talking to client if (oTCPClient != null) { oTCPClient.Close(); } } }
Edit: I get roughly the same numbers on two completely different machines (my XP development machine and field 2003 in the ear). I put some time in the code around the relevant parts (using System.Diagnostic.StopWatch) and uploaded it to the log:
6/6/2009 3:44:50 PM: Debug: While DataAvailable took 0 ms
6/6/2009 3:44:50 PM: Debug: Read took 531 ms
6/6/2009 3:44:50 PM: Debug: ProcessConnection took 577 ms
source share