Создайте простой прокси с помощью сокетов - PullRequest
0 голосов
/ 22 марта 2012

Может кто-нибудь, пожалуйста, помогите мне понять, что я делаю неправильно в своем коде.

Я пытаюсь создать простой HTTP-прокси с использованием сокетов.Я не хочу изменять запросы или ответы в любом случае, я просто хочу иметь возможность ретранслировать запросы / ответы и записывать URL-запросы из браузера.

Этот код не работает должным образом, я понимаю, тамЕсть несколько вопросов по SO, касающихся прокси и сокетов с использованием c #, но я все еще не могу понять, что я делаю неправильно.

Проблема, похоже, связана с моим сокетом. Получите, он медленный и занимает много временивремя для завершения.Браузер ожидает до 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 голосов
/ 02 января 2014

После того, как вы примете сокет, вы должны использовать асинхронную модель и подключить прослушиватель событий для входящих данных с обеих сторон прокси (в клиенте и вне клиента).Это будет держать от блокировки.Затем вы можете избавиться от всех циклов while.

0 голосов
/ 22 марта 2012

Попробуйте профилировать свой код, чтобы увидеть проблемы с производительностью. Попробуйте увеличить размер вашего responseBuffer, улучшить код разбора заголовка (выглядит очень неэффективно получать байты один за другим, преобразовывать их в строку и добавлять в строку с помощью + = вместо StringBuilder и т. Д.), Также вы можете кэшировать подключения к удаленным сервер вместо воссоздания их по каждому запросу и тд. Но перед любыми изменениями всегда лучше профилировать свой код, чтобы увидеть реальную проблему.

Также я бы порекомендовал прочитать несколько примеров хорошего кода для прокси, чтобы научиться некоторым трюкам. Ваш текущий код выглядит очень наивным и неэффективным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...