Ich habe einige Netzwerk-Code, um eine beliebige TCP-Verbindung zu verarbeiten..NET NetworkStream Lesen Langsamkeit
Es scheint alles wie erwartet zu funktionieren, scheint aber langsam. Wenn ich den Code profiliert habe, scheint er gut 600 ms in NetworkStream.Read() zu verbringen und ich frage mich, wie ich ihn verbessern kann. Ich habe mit den Puffergrößen herumgespielt und zwischen einem massiven Puffer gewechselt, um alle Daten in einem Durchgang oder einem kleinen zu lesen, der die Daten in einen StringBuilder verketten sollte. Momentan ist der Client, den ich benutze, ein Webbrowser, aber dieser Code ist generisch und es kann sein, dass es sich nicht um HTTP-Daten handelt, die an ihn gesendet werden. Irgendwelche Ideen?
Mein Code ist dies:
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: Ich ungefähr die gleichen Zahlen auf zwei völlig getrennten Maschinen bekommen (meine XP Entwicklungsmaschine und einen Kasten 2003 in einem Colo). Ich habe einige Timing in den Code um die relevanten Teile setzen (mit System.Diagnostic.StopWatch) und kippen ihn in ein Protokoll:
7/6/2009 3:44:50 PM : Debug : While DataAvailable took 0 ms 7/6/2009 3:44:50 PM : Debug : Read took 531 ms 7/6/2009 3:44:50 PM : Debug : ProcessConnection took 577 ms
Ich habe das gleiche Problem. Ich sehe Ihre Lösung in diesem Beitrag, aber wie wäre es mit den nReadTimeOutMS und bTurboMode. Können Sie mir eine vollständige Beschreibung geben?Ich bin sehr interessiert und geschätzt, wenn Sie diese Klasse mit mir teilen. Danke im Voraus. – olidev
Meine Implementierung war sehr einfach, ich schrieb einen großen Teil davon nach diesem Beitrag um es richtig zu machen. Der Kern der Sache ist, dass Sie sich nur auf Timeouts usw. verlassen, wenn der sendende Client Ihnen nicht sagt, wie viele Daten gesendet werden. Meine neuere Implementierung hat die Header überprüft, um zu sehen, wie viele Daten gesendet wurden und wann alles gelesen wurde, das ich nicht mehr gelesen habe. –