Как правильно работать с http прокси?

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by _nic, 26 Jan 2009.

  1. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    Допустим http заголовок отсылается через сокет а в сокете задается и и порт хттп прокси.Как в этом случае обрабатывать исключительные ситуации возникающие с проксей?
    к примеру если прокси берутся из списка и какая то прокся в этом списке уже сдохла,или это просто не прокся, как это отловить?
    Или я вот недавно пытался получать содержимое хтмл страницы через прокси ,только получалось в 3 из 5 раз.Иногда бывало такое запрос отослался recv вроде как что принимает но в буффере пусто :confused: Почему так случается и как это можно предупредить?
    И где можно посмотреть ошибки которые может возвращять прокся?
     
  2. RaX

    RaX Member

    Joined:
    7 Jun 2008
    Messages:
    34
    Likes Received:
    34
    Reputations:
    0
    На то, сдохла прокся или нет, можешь тупо проверку соединения делать. Чтобы узнать, что это проксик попробуй отсылать http запросы с различными методами для проверки типа OPTIONS, вроде должно помочь ;)
     
  3. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Вообще перед юзаньем прокси попробуй пинговать её, чтобы не терять много времяни на коннект(код пинга - простой очень). Если пингуется то юзаешь её пока нужно. если вдруг connect не прошел то пингуй снова. если не пингуется то удаляй из списка.
    На счет прокси или нет - Удобно очень проверять по контрольной странице. К примеру твой какойнить твой скрипт в инете котоырй будет говорить ОК. Ну или яндекс или подобные вещи. Главное чтобы ты точно знал что смог подключиться.

    На счет recv принимает но буфер пуской. Может ты не правильно загружаешь данные? Или может возникнуть проблема с проверкой буфера если там попадется символ \0

    НА счет кода ответа HTTP прокси то первое что шлет он это будет типа
    HTTP/1.0 404 Not Found
    Сам код можешь получить выбрав среднее слово. типа
    s:='HTTP/1.0 404 Not Found....';
    code:=inttostr(copy(s,pos(' ',s)+1,3));

    Коды ответов сервера ищи в RFC2616 и RFC3143
     
  4. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    Простой ?Это тот который на сырых сокетах?
     
  5. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    нет. стандартными функциями. В более развернутом виде это выглядит так:
    Нижеследующий код с легкостью можно переписать в несколько десятков строк, без дополнительного использования левых модулей.
    Code:
    unit raw_ping;
    
    interface
    uses
      Windows, SysUtils, Classes;
    // Типы данных для настройки пингования
    type
    TSunB = packed record
    s_b1, s_b2, s_b3, s_b4: byte;
    end;
    TSunW = packed record
    s_w1, s_w2: word;
    end;
    PIPAddr = ^TIPAddr;
    TIPAddr = record
    case integer of
     0: (S_un_b: TSunB);
     1: (S_un_w: TSunW);
     2: (S_addr: longword);
    end;
    IPAddr = TIPAddr;
    
    type
     ip_option_information = record
      Ttl : byte;
      Tos : byte;
      Flags : byte;
      OptionsSize : byte;
      OptionsData : pointer;
    end;
    
    type
    ICMP_ECHO_REPLY =
    record
     Address : IPAddr;
     Status : ULONG;
     RoundTripTime : ULONG;
     DataSize : Word;
     Reserved : Word;
     Data : Pointer;
     Options : IP_OPTION_INFORMATION;
     PingBuf: array[0..31] of char;
    end;
    
    
    function IcmpCreateFile : THandle; stdcall; external 'icmp.dll';
    function IcmpCloseHandle (icmpHandle : THandle) : boolean; stdcall; external 'icmp.dll'
    function IcmpSendEcho (IcmpHandle : THandle; DestinationAddress : IPAddr;
        RequestData : Pointer; RequestSize : Smallint;
        RequestOptions : pointer;
        ReplyBuffer : Pointer;
        ReplySize : DWORD;
        Timeout : DWORD) : DWORD; stdcall; external 'icmp.dll';
    
    
    function Ping(InetAddress : string) : boolean;// Пингует заданный адрес
    procedure TranslateStringToTInAddr(AIP: string; var AInAddr);// Конвертирование адреса.
    
    implementation
    
    uses
      WinSock;
    
    procedure TranslateStringToTInAddr(AIP: string; var AInAddr);// Конвертирование адреса
    var
    phe:PHostEnt;
    pac:PChar;
    GInitData:TWSAData;// для работы с библиотекой сокетов
    begin
    WSAStartup($101, GInitData);// Инит библиотеки сокетов
    try
     phe:=GetHostByName(PChar(AIP));// получить адресс сервера по имени
     if Assigned(phe) then
       begin
        pac:=phe^.h_addr_list^;
        if Assigned(pac) then  // Конвертирование
          begin
            with TIPAddr(AInAddr).S_un_b do begin
              s_b1 := Byte(pac[0]);
              s_b2 := Byte(pac[1]);
              s_b3 := Byte(pac[2]);
              s_b4 := Byte(pac[3]);
            end;
          end
          else
          begin
            raise Exception.Create('Error getting IP from HostName');// если ошибка
          end;
        end
        else
        begin
          raise Exception.Create('Error getting HostName');
        end;
      except
        FillChar(AInAddr, SizeOf(AInAddr), #0);
      end;
      WSACleanup;
    end;
    
    
    function Ping(InetAddress : string) : boolean;// пингование
    var
     Handle : THandle;// дискриптор
     InAddr : IPAddr;// Адресс для пингования
     DW:DWORD;//результат пингования
     Reply  : ICMP_ECHO_REPLY;// Буфер для получения ответа ответа
     PingBuf: array[0..31] of char;// Буфер для отправки
    begin
      result := false;// установка что сервер не пингуется
      Handle := IcmpCreateFile;// Создание ICMP
      if Handle = INVALID_HANDLE_VALUE then exit; // Если ошибка, то выход
      TranslateStringToTInAddr(InetAddress, InAddr);// Конвертирование адреса
      Reply.Data := @pingBuf;// Естановка адреса буфера
      Reply.DataSize := 32;// Установка размера бофера
      DW:=IcmpSendEcho(Handle, InAddr, @PingBuf, 32, nil, @reply, SizeOf(icmp_echo_reply)+32  , 3000);// Полыска эхо запроса
      if DW <> 0 then result:=true;// Если !=0 то значит сервак пингуется. Установки пингуеости
      exit;// выход
     // IcmpCloseHandle(Handle); // только для win 9x
    end;
    
    end.
    
    
     
  6. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    А на С примерчик есть?
     
  7. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    функцию резолва (TranslateStringToTInAddr) можеш найти где угодно на Сях.
    А функцию Ping перевести на Си не составит труда. Она и так маленькая и там не используется некаких дельфийских прибамбасов
     
    1 person likes this.
  8. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    IcmpCreateFile и IcmpSendEcho в потоках можно юзать без проблем?