私はプロキシサーバーを作成していますが、それを高性能でスケーラブルにしたいので、 のような低レベルの API を使用することにしましたSystem.Net.Sockets
。
今のところ、Web ブラウザーから要求を受信し、要求をサーバーに転送し、応答をクライアントに再度転送する単純な HTTP プロキシ サーバーを実装しました。私のラップトップのCPU 使用率の100%を消費していることがわかりました。
私は以下のコードを使用していますが、これはシンプルで改善できるので、最初の質問は、CPU 使用率を消費しないように最適化する方法です。コードは次のとおりです。
public void StartHandling()
{
while (!ThreadPool.QueueUserWorkItem(
new WaitCallback(Handler))) ;
}
private void Handler(object obj)
{
bool recvRequest = true;
string EOL = "\r\n";
string requestPayload = "";
string requestTempLine = "";
List<string> requestLines = new List<string>();
byte[] requestBuffer = new byte[1];
byte[] responseBuffer = new byte[1024];
requestLines.Clear();
try
{
//State 0: Handle Request from Client
while (recvRequest)
{
clientSocket.Receive(requestBuffer);
string fromByte = ASCIIEncoding.ASCII.GetString(requestBuffer);
requestPayload += fromByte;
requestTempLine += fromByte;
if (requestTempLine.EndsWith(EOL))
{
requestLines.Add(requestTempLine.Trim());
requestTempLine = "";
}
if (requestPayload.EndsWith(EOL + EOL))
{
recvRequest = false;
}
}
Console.WriteLine("Raw Request Received...");
Console.WriteLine(requestPayload);
//State 1: Rebuilding Request Information and Create Connection to Destination Server
string[] pars = requestLines[0].Split(' ');
string url;
string remoteHost;
string requestFile;
int port;
if (pars[0] == "GET")
{
url = pars[1].Replace("http://", "");
if (url.IndexOf(':') > 0)
throw new InvalidOperationException("Bad request!");
port = 80; // http port
}
else if (pars[0] == "CONNECT")
{
url = pars[1].Replace("https://", "").Replace(":443", "");
if (url.IndexOf(':') > 0)
throw new InvalidOperationException("Bad request!");
port = 443; // https port
}
else
throw new InvalidOperationException("Bad request!");
remoteHost = url.Split('/')[0];
requestFile = requestLines[0].Replace("https://", "").Replace("http://", "").Replace(remoteHost, "");
requestLines[0] = requestFile;
requestPayload = "";
foreach (string line in requestLines)
{
requestPayload += line;
requestPayload += EOL;
}
using (Socket destServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
destServerSocket.Connect(remoteHost, port);
//State 2: Sending New Request Information to Destination Server and Relay Response to Client
destServerSocket.Send(ASCIIEncoding.ASCII.GetBytes(requestPayload));
//Console.WriteLine("Begin Receiving Response...");
while (destServerSocket.Receive(responseBuffer) != 0)
{
//Console.Write(ASCIIEncoding.ASCII.GetString(responseBuffer));
this.clientSocket.Send(responseBuffer);
}
//int totalReceived = destServerSocket.Receive(responseBuffer);
//while (totalReceived != 0)
//{
// clientSocket.Send(responseBuffer, totalReceived, SocketFlags.None);
// totalReceived = destServerSocket.Receive(responseBuffer);
//}
destServerSocket.Disconnect(false);
clientSocket.Disconnect(false);
}
}
catch (Exception e)
{
Console.WriteLine("Error Occured: " + e.Message);
//Console.WriteLine(e.StackTrace);
}
finally
{
clientSocket.Dispose();
Thread.CurrentThread.Abort();
}
}
2 番目の質問は、 HTTPSリクエストをどのように処理できますか? 実際にはHTTPSリクエストをHTTPのようにサーバーに転送しますが、そのようには機能しません。