[DELPHI] Почему несколько потоков пропускают

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by DJ ][akep, 1 Dec 2011.

  1. DJ ][akep

    DJ ][akep Member

    Joined:
    27 Jan 2008
    Messages:
    92
    Likes Received:
    20
    Reputations:
    1
    Вообщем захотел научится делать много поточные приложения и потренироваться на простом чекере прокси на валидность.

    Проблема заключается в том что если программу запустить с 1 потоком, то выводится допустим 10 валидных прокси.
    А если программу запускаю например с 20-ю потоками то находит валидных только 3 и так далее чем больше потоков тем меньше валидных :eek: .

    Вот программа


    Code:
      TNewThread = class(TThread)
      private
    
       FProxy :string;
       FPPort:integer;
       get: string;
       Rez : Integer;
      protected
        procedure Execute; override;
      public
        procedure Sync;
        constructor Create(CreateSuspended: Boolean);
      end;
    
    
    var
      Form1: TForm1;
      Proxys:Tstringlist;
      Thread, Acc, proxy:integer;
      Work:boolean;
      CS:TcriticalSection;
      GoodFile, BadFile: textfile;
    
    implementation
    
    {$R *.dfm}
    
    constructor TNewThread.Create(CreateSuspended: Boolean);
    begin
      inherited Create(CreateSuspended);
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    begin
    
     label1.Caption:='0';
     label2.Caption:='0';
     ProgressBar1.Max:=Proxys.Count;
     ProgressBar1.Position:=0;
     Acc:=-1;
     Proxy:=-1;
     Work:=true;
     for Thread:=1  to strtoint(Edit1.Text) do
      TNewThread.Create(false);
     Thread:=strtoint(Edit1.Text);
    end;
    
    procedure TForm1.Button3Click(Sender: TObject);
    begin
     OpenDialog1.InitialDir:=ExtractFilePath(Application.ExeName);
     if OpenDialog1.Execute then
      begin
       Proxys.Clear;
       Proxys.LoadFromFile(OpenDialog1.FileName);
      end;
    end;
    
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
     Proxys.Free;
    CS.Free;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    Proxys:=Tstringlist.Create;
    CS:=TCriticalSection.Create;
    end;
    
    procedure TNewThread.Execute;
    var
        CurProxy:integer;
    
        HTTP: TIdHTTP;
       // ssl:  TIdSSLIOHandlerSocketOpenSSL;
    begin
     while Work do
      begin
       CS.Enter;
       //Inc(Acc);
       Inc(proxy);
       //if Acc<Accounts.Count then CurAcc:=Acc else Work:=false;
       if proxy<Proxys.Count then CurProxy:=proxy else Work:=false;
       CS.Leave;
    
       if Work then
        begin
    
         FProxy:=Copy(Proxys[CurProxy],1,Pos(':',Proxys[CurProxy])-1);
         FPPort:=StrToInt(Copy(Proxys[CurProxy],Pos(':',Proxys[CurProxy])+1,Length(Proxys[CurProxy])));
         //ssl:=TIdSSLIOHandlerSocketOpenSSL.Create();
         HTTP:=TIdHTTP.create;
         //HTTP.IOHandler:=ssl;
        http.ConnectTimeout:=2000;
         http.ReadTimeout:=2000;
    
    
         HTTP.ProxyParams.ProxyServer:=FProxy;
         HTTP.ProxyParams.ProxyPort:=FPPort;
         HTTP.HandleRedirects:=false;
         try
         get:=HTTP.get('http://ya.ru');
         rez:=-1;
         except
            if Pos('Яндекс', get)<>0 then
           Rez:=1
          else
           Rez:=-1;
         end;
    
    
    
    
         HTTP.Free;
    
    
         Synchronize(Sync);
        end;
      end;
    
     dec(Thread);
     if Thread=0 then ShowMessage('OK');
    end;
    
    procedure TNewThread.Sync;
    begin
     case Rez of
       1:begin
          Form1.Memo1.Lines.Add(FProxy+':'+inttostr(FPPort));
          Form1.label1.Caption:=IntToStr(StrToInt(Form1.label1.Caption)+1);
          Form1.ProgressBar1.Position:=Form1.ProgressBar1.Position+1;
         end;
      -1:begin
          Form1.label2.Caption:=IntToStr(StrToInt(Form1.label2.Caption)+1);
         // form1.Memo1.Lines.Add(get);
          Form1.ProgressBar1.Position:=Form1.ProgressBar1.Position+1;
         end;
     end;
    end;
    
    end.
     
  2. vernite akk=

    vernite akk= New Member

    Joined:
    18 May 2011
    Messages:
    73
    Likes Received:
    2
    Reputations:
    0
    Зачем так извращаться
    Есть же булевые переменые...

    Комменты в коде очень полезная весчь
     
  3. Kandi

    Kandi Member

    Joined:
    18 Nov 2009
    Messages:
    344
    Likes Received:
    17
    Reputations:
    0

    TThreadCheckerUnit.pas
    Code:
    unit ThreadChekerUnit;
    
    interface
    
    uses
      Classes, SysUtils, windows, IdHTTP, IdSSL, IdSSLOpenSSL, IdSocks, IdZLibCompressorBase;
    
    type
      TThreadCheker = class(TThread)
      class var CheckOnMe : Boolean;
      class var TypeProxy : Integer;
      class var TimeOutProxy : Integer;
      private
        { Private declarations }
      protected
        procedure Execute; override;
      end;
    
    implementation
    
    uses MainUnit;
    
    procedure TThreadCheker.Execute;
    var
      HTTP : TIdHTTP;
      SSL : TIdSSLIOHandlerSocketOpenSSL;
      SOCKS : TIdSocksInfo;
      Compress : TIdZLibCompressorBase;
      Server : String;
      Port : Integer;
    begin
      InterlockedIncrement(ThreadCount);
      Sleep(Random(1000));
      while True do
        begin
          if ThreadExit then break;
          HTTP := TIdHTTP.Create(nil);
          Compress := TIdZLibCompressorBase.Create(nil);
          HTTP.Compressor := Compress;
          HTTP.Request.UserAgent := 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.98 Safari/534.13';
          SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
          SOCKS := TIdSocksInfo.Create(nil);
          HTTP.ConnectTimeout := TimeOutProxy * 1000;
          HTTP.ReadTimeout := TimeOutProxy * 1000;
          Synchronize(procedure
          begin
            if IndexProxy >= MainForm.MProxy.Lines.Count then
              ThreadExit := True;
            Server := Trim(MainForm.MProxy.Lines.Names[IndexProxy]);
            Port := StrToInt(Trim(MainForm.MProxy.Lines.ValueFromIndex[IndexProxy]));
            Inc(IndexProxy);
            MainForm.Panel3.Caption := 'Взял прокси: ' + Server + ':' + IntToStr(Port);
            MainForm.Caption := 'Cheker Proxy [' + IntToStr(IndexProxy) + '|' + IntToStr(MainForm.MProxy.Lines.Count) + ']'
          end);
          if ThreadExit then
            begin
              Compress.Free;
              HTTP.Free;
              SSL.Free;
              SOCKS.Free;
              break;
            end;
          case TypeProxy of
            0 : // HTTP
              begin
                HTTP.ProxyParams.ProxyServer := Server;
                HTTP.ProxyParams.ProxyPort := Port;
              end;
            1 : // Socks 4
              begin
                SOCKS.Authentication := saNoAuthentication;
                SOCKS.Version := svSocks4;
                SOCKS.Host := Server;
                SOCKS.Port := Port;
                SSL.TransparentProxy := SOCKS;
                HTTP.IOHandler := SSL;
              end;
            2 : // Socks 5
              begin
                SOCKS.Authentication := saNoAuthentication;
                SOCKS.Version := svSocks5;
                SOCKS.Host := Server;
                SOCKS.Port := Port;
                SSL.TransparentProxy := SOCKS;
                HTTP.IOHandler := SSL;
              end;
          end;
          try
            if Pos('www.artlebedev.ru', HTTP.Get('http://ya.ru')) > 0 then
              Synchronize(procedure begin MainForm.MGood.Lines.Append(Server + ':' + IntToStr(Port)) end);
          except
          end;
          Compress.Free;
          HTTP.Free;
          SSL.Free;
          SOCKS.Free;
        end;
    end;
    
    end.
    
    MainUnit.pas
    Code:
    var
      MainForm: TMainForm;
      ThreadCount : Integer;
      ThreadExit : Boolean;
      IndexProxy : Integer;
      CS : TCriticalSection;
    
    
    procedure TMainForm.BStartClick(Sender: TObject);
    var
      I : Integer;
    begin
      if MProxy.Lines.Count = 0 then exit;
      IndexProxy := 0;
      ThreadCount := 0;
      ThreadExit := False;
      CS := TCriticalSection.Create;
      BStart.Enabled := False;
      BStop.Enabled := True;
      MProxy.Enabled := False;
      SEThreadCount.Enabled := False;
      SETimeOut.Enabled := False;
      RGType.Enabled := False;
      TThreadCheker.TimeOutProxy := SETimeOut.Value;
      TThreadCheker.TypeProxy := RGType.ItemIndex;
      TThreadCheker.CheckOnMe := True;
      for I:=0 to SEThreadCount.Value-1 do
        begin
          Application.ProcessMessages;
          with TThreadCheker.Create(True) do
            begin
              FreeOnTerminate := True;
              OnTerminate := Self.EndThread;
              Resume;
            end;
        end;
    end;
    
    procedure TMainForm.BStopClick(Sender: TObject);
    begin
      ThreadExit := True;
    end;
    
    procedure TMainForm.EndThread(Sender: TObject);
    begin
      Dec(ThreadCount);
      if ThreadCount < 1 then
        begin
          TThreadCheker.CheckOnMe := False;
          SEThreadCount.Enabled := True;
          SETimeOut.Enabled := True;
          RGType.Enabled := True;
          BStart.Enabled := True;
          BStop.Enabled := False;
          MProxy.Enabled := True;
          MainForm.Caption := 'Cheker Proxy';
          CS.Free;
        end;
    end;
    
    procedure TMainForm.FormCreate(Sender: TObject);
    begin
      MProxy.Lines.NameValueSeparator := ':';
      TThreadCheker.CheckOnMe := False;
    end;
    
    procedure TMainForm.MGoodChange(Sender: TObject);
    begin
      Panel2.Caption := 'Загруженно: ' + IntToStr(MGood.Lines.Count);
      if MGood.Lines.Count = 0 then
        Panel2.Caption := '';
    end;
    
    procedure TMainForm.MProxyChange(Sender: TObject);
    begin
      Panel1.Caption := 'Загруженно: ' + IntToStr(MProxy.Lines.Count);
      if MProxy.Lines.Count = 0 then
        Panel1.Caption := '';
    end;
    
    Ничего не теряет и ничего не пропускает :)
     
  4. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    ReadTimeOut и ConnectionTimeOut по 2к это мало.
    тут даже без прокси не всегда впишетесь

    Code:
         try
         get:=HTTP.get('http://ya.ru');
         rez:=-1;
         except
            if Pos('Яндекс', get)<>0 then
           Rez:=1
          else
           Rez:=-1;
         end;
    хм. а разве Indy при Exception'e возвращает не пустую строку?
    UPD: итить колотить, он походу возвращает Вам, что прокси жив из-за того, что переменная rez не инициируется из-за Exception'a
     
    #4 xophet, 1 Dec 2011
    Last edited: 1 Dec 2011
  5. DJ ][akep

    DJ ][akep Member

    Joined:
    27 Jan 2008
    Messages:
    92
    Likes Received:
    20
    Reputations:
    1
    Работает аж дух захватывает!
    Спасибо вам огромное за данный пример. Буду учится! :)
     
  6. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Сам понял че сказал?)
     
  7. DJ ][akep

    DJ ][akep Member

    Joined:
    27 Jan 2008
    Messages:
    92
    Likes Received:
    20
    Reputations:
    1
    Причина по которой моя программа не правильно работала заключалась в неверном использовании try.
    Но тут возникла проблема!
    Как в предложенной версии "Kandi", так и в моей если включить SSL, не в соках .
    Без SSL работает всё отлично, но мне нужно прокси чекать именно на доступ к определенному сайту, а также брать кое-какие данные в случае успеха.
    Если допустим взять и отчекать лист, сохранить его и попытаться отчекать званого, программы просто вылетает.
    [​IMG]

    Код:
    http://pastebin.com/3X9e3wGn

    Исходник всего проекта:
    http://rghost.ru/33042801
     
    #7 DJ ][akep, 3 Dec 2011
    Last edited: 3 Dec 2011
  8. vernite akk=

    vernite akk= New Member

    Joined:
    18 May 2011
    Messages:
    73
    Likes Received:
    2
    Reputations:
    0
    Длл нормльные в папке с софтом лежат?
    Те что по дефолту идут для работы с ссл вроде досихпор глюченые.
     
  9. DJ ][akep

    DJ ][akep Member

    Joined:
    27 Jan 2008
    Messages:
    92
    Likes Received:
    20
    Reputations:
    1
    Причем тут dll?
    В программе используются стандартные vcl библиотеки "TIdSSLIOHandlerSocketOpenSSL"
     
  10. vernite akk=

    vernite akk= New Member

    Joined:
    18 May 2011
    Messages:
    73
    Likes Received:
    2
    Reputations:
    0
    Да ты прав причем тут они это же стандартные VCL классы, был не прав сорри, уверен и без длл и с бажными длл все ок пахать будет.Есче раз извини ТС за мой глупый совет пошел курить маны по стандартныи VCL классам...