使用套接字编写代理服务器和客户端

时间:2013-05-30 19:21:32

标签: c# .net sockets proxy

我正在使用代理服务器并希望它具有高性能和scalabe,因为我决定使用像System.Net.Sockets这样的低级api。

截至目前,我刚刚实现了一个简单的http代理服务器,它接收来自Web浏览器的请求,并简单地将请求转发给服务器,然后再将响应转发给客户端。事实证明,它消耗了 100%我的笔记本电脑的 CPU使用率

我使用下面的代码,这很简单,可以改进,所以我的第一个问题是如何优化它以便不占用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();
        }
    }

我的第二个问题是如何处理 HTTPS 请求的?我实际上将HTTPS请求转发到服务器,就像HTTP一样,但它不能那样工作。

0 个答案:

没有答案