任意のTCP接続を処理するためのネットワークコードがあります。.NET NetworkStream低速読み取り
これはすべて期待どおりに機能するようですが、遅いようです。コードをプロファイリングすると、NetworkStream.Read()で600ミリ秒を費やすように見え、それを改善する方法が不思議です。私は、バッファサイズを手抜きして、大量のバッファを交互に読み込んで、すべてのデータを読み込んだり、小さなデータをStringBuilderに連結したりする必要がありました。現在私が使用しているクライアントはWebブラウザですが、このコードは一般的なもので、送信されるHTTPデータではない可能性があります。何か案は?
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();
}
}
}
編集:
私のコードはこれである私は、大きく分けて2台の完全に別々のマシン(私のXPの開発マシンと結腸で2003箱)に同じ数値を取得します。私は、関連する部分(System.Diagnostic.StopWatchを使用して)周りのコードにいくつかのタイミングを入れて、ログにそれをダンプしました:
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
私は同じ問題を抱えています。私はこの記事であなたの解決策を見ていますが、nReadTimeOutMSとbTurboModeについてはどうでしょうか。私に完全な説明を教えてください。私はこのクラスを私と共有すれば、とても興味があり、感謝しています。前もって感謝します。 – olidev
私の実装は非常に基本的なものだったので、私はこのポストの後でそれを正しく行うために大きなチャンクを書きました。問題の要点は、送信側のクライアントがどれくらいのデータを送信しているかを伝えていない場合にのみタイムアウトなどに依存することです。私の最近の実装では、ヘッダーをチェックして、送信されたデータの量と、読み込みを停止したすべてのデータを読み取った時刻を確認しました。 –