Авторские статьи Бесформенное использование INDY на примере Id http ProxyServer

Discussion in 'Статьи' started by begin_end, 19 Apr 2007.

  1. begin_end

    begin_end Green member

    Joined:
    4 Jan 2007
    Messages:
    265
    Likes Received:
    638
    Reputations:
    476
    Цели данной, совсем небольшой, статьи:

    рассказать о способе использования компонентов INDY, не применяя VCL-формы Дельфи (зачем это нужно: это делает ваши приложения оптимальнее, сильно сокращает размер);
    показать возможность быстрого и простого создания прокси-сервера.

    Рассчитано на программистов на Дельфи, работающих с INDY-компонентами.

    Начну с того, что кратко скажу об обычном применении компонентов INDY на примере idHTTPProxyServer.
    Внимание: он отсутствует в INDY версии 9 (которая с Дельфи 7), необходимо обновить до 10 версии.

    Создаем пустую форму. На вкладке компонентов ищем Indy Servers ит там будет idHTTPProxyServer. Кладём его на форму. Далее в параметрах компонента указываем порт, например, 81 и Active=true. Запускаем приложение и мы уже можем соединятся с ним по 81 порту. Прокси сервер готов! Но приложение имеет вес более 500 Кб и не нужную нам форму. Как же быть? А так: сделаем часть приложения, необходимую в качестве основы для INDY-компонента на чистом API. Для этого нам понадобится 6 API-функций: RegisterClass, GetMessage, TranslateMessage, DispatchMessage, DefWindowProc, PostQuitMessage. Также нужно будет создать класс и реализовать приём и обработку сообщений. В uses мы указываем только одно – idHTTPProxyServer. Сам прокси-сервер создаётся всего тремя строчками кода. Используем модуль, вызываем функции и обрабатываем сообщения так:

    Code:
    program Project1;
    //файл ресурсов (иконка и проч.)
    {$R *.res}
    
    //используем инди-модуль
    uses IdHTTPProxyServer;
    
    const
    //title нашего класса
      WND_TITLE  = 'PSrv';
    //имя нашего класса
      WND_CLASS  = 'PSrv';
      user32     = 'user32.dll'; 
    
    //вызываемые API-функции
      function RegisterClass(lpWndClass: Pointer): Cardinal; stdcall; external user32 name 'RegisterClassA';
      function GetMessage(lpMsg: Pointer; hWnd, wMsgFilterMin, wMsgFilterMax: Cardinal): boolean; stdcall; external user32 name 'GetMessageA';
      function TranslateMessage(lpMsg: Pointer): Boolean; stdcall; external user32 name 'TranslateMessage';
      function DispatchMessage(lpMsg: Pointer): Integer; stdcall; external user32 name 'DispatchMessageA'
      function DefWindowProc(hWnd, Msg: Cardinal; wParam, lParam: Integer): Integer; stdcall; external user32 name 'DefWindowProcA';
      procedure PostQuitMessage(nExitCode: Integer); stdcall; external user32 name 'PostQuitMessage';
    
    //обработчик сообщений
    function WndProc(hwnd, message: Cardinal; wParam, lParam: Integer): Integer; stdcall;
    begin
      if message = $0002 then
      begin
        PostQuitMessage(0);
        Result := 0;
      end else
        Result := DefWindowProc(hwnd, message, wParam, lParam);
    end;
    А, теперь нужно описать структуры класса wnd и сообщения msg. И собственно вставить сам рабочий код, создающий и запускающий прокси-сервер:

    Code:
    var
    //структура wnd
      wnd : packed record
        style         : Cardinal;
        lpfnWndProc   : Pointer;
        cbClsExtra    : Integer;
        cbWndExtra    : Integer;
        hInstance     : Cardinal;
        hIcon         : Cardinal;
        hCursor       : Cardinal;
        hbrBackground : Cardinal;
        lpszMenuName  : PAnsiChar;
        lpszClassName : PAnsiChar;
      end = (
        lpfnWndProc   : @WndProc;
        hbrBackground : 0;
        lpszClassName : WND_CLASS);
    
    
    var
    //определяем прокси-сервер
       IdHTTPProxyServer1: TIdHTTPProxyServer;
    //структура msg
       msg : packed record
        hwnd    : Cardinal;
        message : Cardinal;
        wParam  : Integer;
        lParam  : Integer;
        time    : Cardinal;
        X, Y    : Integer;
      end;
    
    begin
    //регистрируем класс wnd
      RegisterClass(@wnd);
    //создаём прокси-сервер
      IdHTTPProxyServer1:=TIdHTTPProxyServer.Create;
    //указываем порт, по какому он будет доступен
      IdHTTPProxyServer1.DefaultPort:=81;
    //запускаем прокси-сервер
      IdHTTPProxyServer1.Active:=true;
    //приём сообщений структуры msg и их трансляция
        while GetMessage(@msg, 0, 0, 0) do
      begin
        TranslateMessage(@msg);
        DispatchMessage(@msg);
      end;
    end.
    Этот исходный код и готовое приложение можно скачать здесь. Приложение, упакованное UPX, весит всего 93,5Кб. В работе испытано, работает надёжно. Описанный метод применим к работе с прочими INDY-компонентами, например с idHTTPServer или idSMTP.

    Статья и пример были созданы в образовательных целях, по просьбам интересующихся. В ходе работы использовалась среда Delphi 7, но набор компонентов INDY версии 10. Статью можно дополнять, переопубликовывать с разрешения автора. Предложения и критика ожидаемы и желательны.
     
    _________________________
    6 people like this.
  2. Fen-Omen

    Fen-Omen Elder - Старейшина

    Joined:
    22 Mar 2007
    Messages:
    60
    Likes Received:
    88
    Reputations:
    60
    Сильно - это насколько в персентах будет?
     
  3. begin_end

    begin_end Green member

    Joined:
    4 Jan 2007
    Messages:
    265
    Likes Received:
    638
    Reputations:
    476
    Программа с idHTTPProxyServer и формой на VCL занимает размер 195Кб в упакованном виде. Описанная в статье - 93,5Кб. Получается, что на 48% или почти в два раза меньше.
     
    _________________________
    2 people like this.
  4. felix_v26

    felix_v26 New Member

    Joined:
    19 Mar 2011
    Messages:
    20
    Likes Received:
    0
    Reputations:
    0
    а если этот прокси запустить на компе который подключен к инету через wifi роутер... как можно подключиться к этому прокси из инета( к какому ip коннектится, или может надо чтото ещё донастроить )?