Конференция "Сети" » Дайте пример HTTP прокси на WinSock!! Без VCL/
 
  • Dennis I. Komarov © (29.10.09 09:09) [20]

    > Anatoly Podgoretsky ©   (28.10.09 10:32) [18]

    Не, он посадить хочет, а там пускай думает :)


    > А то, что у г-на Фленова имеются некоторые ошибки, так это
    > даже хорошо...
    > Человеку будет над чем подумать: как это исправить чтобы
    > работало.
  • Anatoly Podgoretsky © (29.10.09 11:39) [21]
    > SergP  (28.10.2009 19:58:19)  [19]

    > ну а если уважаемый АП считает, что такой метод помощи в корне неверен, у него имеется полное право удалить мои сообщения.

    Зачем мне это нужно?
    Пока нет нарушения правил, имеешь право писать, но и другие тоже!!!
  • Anatoly Podgoretsky © (29.10.09 11:40) [22]
    > Dennis I. Komarov  (29.10.2009 09:09:20)  [20]

    Ты думаешь, что он сможет остаться в стороне, да я бы на месте автора все свалил на него!
  • Dennis I. Komarov © (29.10.09 12:40) [23]

    > Anatoly Podgoretsky ©   (29.10.09 11:40) [22]

    Тогда в итоге Фленову отдуваться за все его тяжкие... :)
  • Демо © (29.10.09 14:03) [24]
    program proxy;

    {$APPTYPE CONSOLE}

    {%TogetherDiagram 'ModelSupport_proxy\default.txaPackage'}

    uses
    SysUtils,
    Windows,
    Winsock,
    Classes;

    type
    TCompletionPort=class
    public
     FHandle:THandle;
     constructor Create(dwNumberOfConcurentThreads:DWORD);
     destructor Destroy;override;
     function AssociateDevice(hDevice:THandle;dwCompKey:DWORD):boolean;
    end;

    TAcceptThread=class(TThread)
    private
     FListenSocket:TSocket;
     FListenPort:Word;
     FClientList:TList;
     procedure GarbageCollect;
    protected
     procedure Execute;override;
    public
     constructor Create(AListenPort:Word);reintroduce;
     destructor Destroy;override;
    end;

    type
    TClientThread=class(TThread)
    public
     procedure Execute;override;
    end;

    type
    TClient=class
    private
     FSocket:TSocket;
     FEvent:THandle;
     ov:POVERLAPPED;
     Buffer:Pointer;
     BufSize:Cardinal;
     procedure Write(Buf:Pointer;Size:Cardinal);
    public
     FOppositeClient:TClient;
     FLastActivity:double;
     constructor Create;
     destructor Destroy;override;
     procedure Connect(ARequest:string);
     procedure Disconnect;
     procedure Complete(dwNumBytes:Cardinal);virtual;abstract;
    end;

    TInternalClient=class(TClient)
    public
     procedure Complete(dwNumBytes:Cardinal);override;
    end;

    TExternalClient=class(TClient)
    public
     procedure Complete(dwNumBytes:Cardinal);override;
    end;

    //-------------------------------implementation-------------------------------

    var
     FCompPort:TCompletionPort;

    { TCompletionPort }

    constructor TCompletionPort.Create(dwNumberOfConcurentThreads: DWORD);
    begin
     FHandle:=CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,dwNumberOfConcurentThre ads);
    end;

    function TCompletionPort.AssociateDevice(hDevice: THandle;
     dwCompKey: DWORD): boolean;
    begin
    result:=CreateIoCompletionPort(hDevice,FHandle,dwCompKey,0)=FHandle;
    end;

    destructor TCompletionPort.Destroy;
    begin
     CloseHandle(FHandle);
     inherited;
    end;

    { TAcceptThread }

    constructor TAcceptThread.Create(AListenPort: Word);
    begin
     inherited Create(false);
    FListenPort:=AListenPort;
     FClientList:=TList.Create;
    end;

    destructor TAcceptThread.Destroy;
    begin
     FClientList.Free;
     inherited;
    end;

    procedure TAcceptThread.GarbageCollect;
    var
     AClient:TClient;
    i:integer;
    begin
    for i:=0 to FClientList.Count-1 do
     begin
       AClient:=TClient(FClientList[i]);
     if Assigned(AClient) then
      if (AClient.FSocket=INVALID_SOCKET) and ((now-AClient.FLastActivity)>7E-4) then
      begin
       FClientList[i]:=nil;
       if Assigned(AClient.FOppositeClient) then AClient.FOppositeClient.Free;
       AClient.Free;
      end;
    end;
    FClientList.Pack;
    FClientList.Capacity:=FClientList.Count;
    end;

    procedure TAcceptThread.Execute;
    var
    FAddr: TSockAddrIn;
    Len: Integer;
    ClientSocket:TSocket;
    InternalClient:TClient;
    begin
    FListenSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    FAddr.sin_family := PF_INET;
    FAddr.sin_addr.s_addr := INADDR_ANY;
    FAddr.sin_port := htons(FListenPort);
    bind(FListenSocket, FAddr, SizeOf(FAddr));
    listen(FListenSocket, SOMAXCONN);

    try
     while not Terminated do
     begin
      Len:=sizeof(FAddr);
      ClientSocket:=accept(FListenSocket, @FAddr, @Len);
      try
       GarbageCollect;
       if ClientSocket<>INVALID_SOCKET then
       begin
        InternalClient:=TInternalClient.Create;
        InternalClient.FSocket:=ClientSocket;
        FClientList.Add(InternalClient);
        FCompPort.AssociateDevice(InternalClient.FSocket,Cardinal(InternalClient));
        InternalClient.Complete(0);
       end;
      except
      end;
     end;
    finally
     shutdown(FListenSocket,2);
     closesocket(FListenSocket);
    end;
    end;

    { TClientThread }

    procedure TClientThread.Execute;
    var
    CompKey,dwNumBytes:Cardinal;
    ov:POVERLAPPED;
    begin
    try
     while not Terminated do
     begin
      if GetQueuedCompletionStatus(FCompPort.FHandle,dwNumBytes,CompKey,ov,INFINITE) and (dwNumBytes>0) then
      begin
       if TClient(CompKey).FSocket<>INVALID_SOCKET then
       begin
        TClient(CompKey).Complete(dwNumBytes);
        TClient(CompKey).FLastActivity:=now;
       end;
      end
      else
       TClient(CompKey).Disconnect;
     end;
    except
     TClientThread.Create(false);
     end;
    end;

    { TClient }

    constructor TClient.Create;
    begin
    FSocket:=INVALID_SOCKET;
    BufSize:=8192;
    GetMem(Buffer,BufSize);
    new(ov);
    ov.Internal:=0;
    ov.InternalHigh:=0;
    ov.Offset:=0;
    ov.OffsetHigh:=0;
    ov.hEvent:=0;
    FEvent:=CreateEvent(nil,true,false,nil);
    FLastActivity:=now;
    end;

    destructor TClient.Destroy;
    begin
    Disconnect;
    CloseHandle(FEvent);
    FreeMem(Buffer);
    Dispose(ov);
    inherited;
    end;

    procedure TClient.Connect(ARequest: string);
    var
    f,t:integer;
    ARemoteAddress:string;
    ARemotePort:string;
    he:PHostEnt;
    FAddr:TSockAddrIn;
    begin
    f:=Pos('/',ARequest)+2;
    t:=Pos('HTTP',ARequest)-1;
    ARemoteAddress:=Copy(ARequest,f,t-f);
    t:=Pos('/',ARemoteAddress);
    if t<>0 then ARemoteAddress:=Copy(ARemoteAddress,0,t-1);
    t:=Pos(':',ARemoteAddress);
    if t<>0 then
    begin
     ARemotePort:=Copy(ARemoteAddress,t+1,Length(ARemoteAddress)-t);
     ARemoteAddress:=Copy(ARemoteAddress,0,t-1);
     end
    else
       ARemotePort:='80';

     he:=GetHostByName(PChar(ARemoteAddress));
     if not Assigned(he) then exit;
     ARemoteAddress:=inet_ntoa(PInAddr(he.h_addr_list^)^);

     FSocket:=socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
    FAddr.sin_family:=PF_INET;
     FAddr.sin_addr.s_addr :=inet_addr(PChar(ARemoteAddress));
     try
       FAddr.sin_port := htons(StrToInt(ARemotePort));
     if WinSock.connect(FSocket, FAddr, SizeOf(FAddr))=SOCKET_ERROR then FSocket:=INVALID_SOCKET;
    except
     end;
    end;

    procedure TClient.Disconnect;
    begin
    if FSocket<>INVALID_SOCKET then
    begin
     shutdown(FSocket,2);
     closesocket(FSocket);
     FSocket:=INVALID_SOCKET;
     if Assigned(FOppositeClient) then FOppositeClient.Disconnect;
    end;
    end;

    procedure TClient.Write(Buf: Pointer; Size: Cardinal);
    var
    BytesWrite:Cardinal;
    begin
    ov.hEvent:=FEvent or 1;
    WriteFile(FSocket,Buf^,Size,BytesWrite,ov);
    ov.hEvent:=0;
    end;

    { TInternalClient }

    procedure TInternalClient.Complete(dwNumBytes: Cardinal);
    var
    BytesRead:Cardinal;
    begin
    if dwNumBytes>0 then
    begin
     if not Assigned(FOppositeClient) then
     begin
      FOppositeClient:=TExternalClient.Create;
      FOppositeClient.FOppositeClient:=self;
      FOppositeClient.Connect(PChar(Buffer));
      if FOppositeClient.FSocket=INVALID_SOCKET then
      begin
       Disconnect;
       exit;
      end;
      FCompPort.AssociateDevice(FOppositeClient.FSocket,Cardinal(FOppositeClient));
      FOppositeClient.Complete(0);
     end;
     FOppositeClient.Write(Buffer,dwNumBytes);
    end;
    ReadFile(FSocket,Buffer^,BufSize,BytesRead,ov);
    end;

    { TExternalClient }

    procedure TExternalClient.Complete(dwNumBytes: Cardinal);
    var
    BytesRead:Cardinal;
    begin
    if dwNumBytes>0 then FOppositeClient.Write(Buffer,dwNumBytes);
    ReadFile(FSocket,Buffer^,BufSize,BytesRead,ov);
    end;

    const
    ClientThreadCount:integer=10;
    ListenPort:Dword=8080;

    var
    WSAData:TWSAData;
    Cnt:Cardinal;
    i:integer;
    begin
    FCompPort:=TCompletionPort.Create(ClientThreadCount);
    if FCompPort.FHandle<>0 then
    begin
       WSAStartup($0101, WSAData);
       for i:=0 to ClientThreadCount-1 do TClientThread.Create(false);
       TAcceptThread.Create(ListenPort);
       ReadConsole(GetStdHandle(STD_INPUT_HANDLE),nil,0,Cnt,nil);
       WSACleanup;
     end;
    end.

  • Демо © (29.10.09 14:05) [25]
    Забыл автора добавить:

    {*******************************************************}
    {                                                       }
    {                  HTTP Proxy Server                    }
    {                                                       }
    {         Copyright © 2002 Sergey Polevikov           }
    {                                                       }
    {*******************************************************}
  • Сергей М. © (29.10.09 14:54) [26]
    Еще один Фленов объявился)
  • Демо © (29.10.09 15:05) [27]

    > Еще один Фленов объявился)


    Э-э... В смысле?
  • Сергей М. © (29.10.09 15:19) [28]
    Да в том же самом)
    См. выше)
  • Демо © (29.10.09 15:27) [29]

    > Сергей М. ©   (29.10.09 15:19) [28]
    > Да в том же самом)См. выше)


    Это далеко не флёновский код-)

    И автор местный;)

    А код очень полезный, если в нём разобраться, хоть и подготовка для этого не начального уровня нужна...
  • Сергей М. © (29.10.09 15:37) [30]

    > Это далеко не флёновский код


    Но зато вполне фленовский подход)

    И автор мне достаточно известен)


    > код очень полезный, если в нём разобраться


    Так я и говорю - ты сейчас пропагандируешь тот же самый "фленовский подход" к получению знаний)
  • Демо © (29.10.09 16:04) [31]

    > Так я и говорю - ты сейчас пропагандируешь тот же самый
    > "фленовский подход" к получению знаний)


    Иногда ведь полезнее изучить чужой код, чтобы понять принципы, нежели изобретать велосипед.
  • Dennis I. Komarov © (29.10.09 16:25) [32]

    > Иногда ведь полезнее изучить чужой код, чтобы понять принципы,
    >  нежели изобретать велосипед.

    Действительно в это веришь? Всмысле, что его будут изучать?
  • Демо © (29.10.09 16:32) [33]

    > Действительно в это веришь? Всмысле, что его будут изучать?


    А почему нет?.
    Для меня, когда я этот код первый раз увидел, необходимо было его изучить и понять, чтобы написать своё.

    Да даже чтобы изменить.

    Ну а если пригодится в таком виде - да ради бога, - на здоровье.
    Ничего страшного в копипасте нет.
  • Anatoly Podgoretsky © (29.10.09 16:34) [34]
    > Демо  (29.10.2009 16:04:31)  [31]

    Полезно изучать, именно изучать, хороший, профессиональный код. При том желательно, что бы это были примеры демонстрирующие принципы, а не готовый код. Я всегда, при освоении нового, особенно технологий, смотрю примеры, а готовый рабочий код мне неинтересен, от него толку не много.
  • Демо © (29.10.09 16:39) [35]

    > Anatoly Podgoretsky ©   (29.10.09 16:34) [34]
    > > Демо  (29.10.2009 16:04:31)  [31]Полезно изучать, именно
    > изучать, хороший, профессиональный код. При том желательно,
    >  что бы это были примеры демонстрирующие принципы, а не
    > готовый код. Я всегда, при освоении нового, особенно технологий,
    >  смотрю примеры, а готовый рабочий код мне неинтересен,
    > от него толку не много.


    Иногда для своей задачи необходим промежуточный компонент.
    Например, для получения всех запросов от браузера нужно либо снифер изучать, либо пустить запросы через прокси.

    Для чего мне в данном случае изучать внутренность прокси, если мне оно не нужно, а нужен результат?
  • Сергей М. © (29.10.09 16:44) [36]

    > Демо ©   (29.10.09 16:32) [33]
    > А почему нет?.


    Потому что топикстарт изрядно отдает курсачем или даже лабой)
  • Anatoly Podgoretsky © (29.10.09 16:51) [37]
    > Демо  (29.10.2009 16:39:35)  [35]

    В этом случае прокси не нужен, а нужен форвард портов со шпионом. Например шпион есть в Инди
  • Dennis I. Komarov © (29.10.09 16:52) [38]

    > В этом случае прокси не нужен, а нужен форвард портов со
    > шпионом. Например шпион есть в Инди

    В этом случае вообще писать ничего не надо...
  • Демо © (29.10.09 18:13) [39]

    > В этом случае прокси не нужен, а нужен форвард портов со
    > шпионом. Например шпион есть в Инди


    Что, ещё и файрволл ставить для этого?


    > Dennis I. Komarov ©   (29.10.09 16:52) [38]
    > > В этом случае прокси не нужен, а нужен форвард портов
    > со > шпионом. Например шпион есть в ИндиВ этом случае вообще
    > писать ничего не надо...


    Ну-ка, ну-ка, поподробнее...
 
Конференция "Сети" » Дайте пример HTTP прокси на WinSock!! Без VCL/
Есть новые Нет новых   [118230   +16][b:0][p:0.004]