使用套接字创建一个简单的代理

时间:2012-03-22 08:32:12

标签: c# sockets proxy

有人可以帮我弄清楚我的代码中出错了吗。

我正在尝试使用套接字创建一个简单的HTTP代理。我不想以任何方式更改请求或响应,我只是希望能够中继请求/响应并记录来自浏览器的URL请求。

这段代码工作不正常,我发现有几个关于使用c#的代理和套接字的问题,但我仍然无法弄清楚我做错了什么。

问题似乎是我的socket.receive,它很慢,需要很长时间才能完成。浏览器等待最多10/20秒......

   int bytes = 0;
                do
                {
                    bytes = destServerSocket.Receive(responseBuffer);
                    client.Send(responseBuffer);
                }
                while (bytes > 0);

有时我在发送标题时得到(SocketException:远程主机强行关闭现有连接)。

有时候我收到一个(SocketException:已建立的连接被主机中的软件中止)

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace Proxy
{
    class Program
    {

        static void Main(string[] args)
        {
            TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 8888);
            server.Start();

            while (true)
            {
                Socket client = server.AcceptSocket();
                Thread t = new Thread(new ParameterizedThreadStart(Program.Handle));
                t.Start(client);
                //Thread.Sleep(30);
            }
        }

        static void Handle(object clientSocket)
        {
            Socket client = (Socket)clientSocket;
            bool recveiveRequest = true;
            string EOL = "\r\n";

            string headers = "";
            string requestTempLine = "";
            List<string> requestLines = new List<string>();
            byte[] requestBuffer = new byte[1];
            byte[] responseBuffer = new byte[1024];

            Socket destServerSocket = null;

            requestLines.Clear();

            try
            {
                while (recveiveRequest)
                {
                    client.Receive(requestBuffer);
                    string fromByte = ASCIIEncoding.ASCII.GetString(requestBuffer);
                    headers += fromByte;
                    requestTempLine += fromByte;

                    if (requestTempLine.EndsWith(EOL))
                    {
                        requestLines.Add(requestTempLine.Trim());
                        requestTempLine = "";
                    }

                    if (headers.EndsWith(EOL + EOL))
                    {
                        recveiveRequest = false;
                    }
                }
                Console.WriteLine("Raw Request Received...");
                Console.WriteLine(headers);

                // TODO: record headers

                string remoteHost = requestLines[0].Split(' ')[1].Replace("http://", "").Split('/')[0];
                string requestFile = requestLines[0].Replace("http://", "").Replace(remoteHost, "");
                requestLines[0] = requestFile;

                headers = "";
                foreach (string line in requestLines)
                {
                    headers += line;
                    headers += EOL;
                }

                destServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                destServerSocket.Connect(remoteHost, 80);
                destServerSocket.Send(ASCIIEncoding.ASCII.GetBytes(headers));

                int bytes = 0;
                do
                {
                    bytes = destServerSocket.Receive(responseBuffer);
                    client.Send(responseBuffer);
                }
                while (bytes > 0);

            }
            catch (Exception e)
            {
                Console.WriteLine("Error Occured: " + e.Message);
            }
            finally
            {
                destServerSocket.Close();
                client.Close();
            }
        }

    }
}

谢谢,任何帮助表示赞赏...

2 个答案:

答案 0 :(得分:0)

尝试分析您的代码以查看性能问题。尝试增加responseBuffer的大小,改进头解析代码(逐个接收字节看起来非常低效,将它们转换为字符串并使用+ =而不是StringBuilder添加到字符串等),还可以缓存到远程的连接服务器而不是在每个请求上重新创建它们等等。但在进行任何更改之前,最好分析您的代码以查看真正的问题。

另外,我建议您阅读一些代理的好代码示例来学习一些技巧。您当前的代码看起来非常天真和低效。

答案 1 :(得分:0)

一旦接受了套接字,就应该使用异步模型并为来自代理两端的传入数据(在客户端和客户端中)挂钩事件监听器。这将阻止阻止。然后你可以摆脱所有的while循环。

相关问题