任意の TCP 接続を処理するためのネットワーク コードがいくつかあります。
すべてが期待どおりに機能しているように見えますが、遅いようです。コードのプロファイリングを行ったところ、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 を使用)、ログにダンプしました。
2009 年 7 月 6 日 3:44:50 PM: デバッグ: DataAvailable が 0 ミリ秒かかった間 2009/7/6 3:44:50 PM: デバッグ: 読み取りに 531 ミリ秒かかりました 2009 年 7 月 6 日 3:44:50 PM: デバッグ: ProcessConnection に 577 ミリ秒かかりました