Многопоточный чеккер прокси под VK своими руками. Delphi

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by ErrorNeo, 25 Sep 2009.

  1. mazaxaka

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

    Joined:
    15 Feb 2008
    Messages:
    268
    Likes Received:
    35
    Reputations:
    0
    Програма то компилируется..
    файл с прокси есть
    гуд тоже создал
    ставлю таймаут
    жму батом1
    и нечего..

    а ругается вот на ету
    и ету строки
    строки
     
  2. 0rs

    0rs Member

    Joined:
    30 Dec 2008
    Messages:
    70
    Likes Received:
    23
    Reputations:
    3
    На асме у меня такой код для таймаута работает:
    Code:
    LOCAL timeout: timeval
    LOCAL fds: fd_set
    LOCAL block: DWORD
    
    ;подключение
    	mov block, 1
    	invoke ioctlsocket, hSock, FIONBIO, addr block
    	invoke connect, hSock, addr sin, sizeof sin
    	mov block, 0
    	invoke ioctlsocket, hSock, FIONBIO, addr block
    ;таймаут
    	mov timeout.tv_sec, 3
    	mov timeout.tv_usec, 0
    	mov eax, 1
    	mov fds.fd_count, eax
    	mov eax, hSock
    	mov fds.fd_array, eax
    	invoke select, 0, addr fds, addr fds, 0, addr timeout
    	.if eax==0
    		invoke closesocket, hSock
    		mov eax, 5
    		ret
    	.endif
    
    На дельфи вроде так будет выглядеть, но на работоспособность не проверял:
    Code:
    var
    	timeout: timeval;
    	fds: fd_set;
    	block: DWORD;
    begin
    	block:=1;
    	ioctlsocket(hSock, FIONBIO, block);
    	connect(hSock, sin, sizeof (sin));
    	block:=0;
    	ioctlsocket(hSock, FIONBIO, block);
    	timeout.tv_sec:= 3;
    	timeout.tv_usec:= 0;
    	fds.fd_count:= 1;
    	fds.fd_array:= hSock;
    	if select(0, fds, fds, 0, timeout)=0 then
    	begin
    		\\Подключиться не удалось
    	end;
    end;
    
    Может быть стоит вообще поставить таймаут на поток, тогда не будет необходимости ставить таймауты на подключение, запись и чтение.
    А имеет ли вообще смысл чекать прокси? Может быть лучше перед началом работы заносить все прокси в список или массив sockaddrin, а во время выполнения основного функционала (например проверка акков на валидность) занулять или удалять из списка нерабочие.
     
    #22 0rs, 14 Oct 2009
    Last edited: 14 Oct 2009
  3. ErrorNeo

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

    Joined:
    2 May 2009
    Messages:
    923
    Likes Received:
    838
    Reputations:
    402
    0rs
    ну я не собирался писать "многопоточный спамер по личкам ВК своими руками", потому написал безобидный пример) Кому надо - тот допишет сколько то строк сам.
    Спс за _примерный_ пример таймаута на коннект. Будет время погуглю как это правильно пишется и добавлю.

    mazaxaka
    видимо у тебя дельфи-7 - я писал на дельфи 6.
    Перенеси переменную counter_1 из глобальных в переменные функции Button1.click, и все заработает.
     
  4. GhostOnline

    GhostOnline Active Member

    Joined:
    20 Dec 2008
    Messages:
    723
    Likes Received:
    110
    Reputations:
    22
    Спс за сорцы.
    Только один вопрос: почему ты используешь 2 крит. секции? Почему не одну?
     
  5. ErrorNeo

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

    Joined:
    2 May 2009
    Messages:
    923
    Likes Received:
    838
    Reputations:
    402
    2 крит секции потому что работа идет с 2 файлами.

    Не имеет смысла блокировать доступ к файлу good.txt из-за того, что идет работа с proxy.txt. А вот быстродействию кода это заметно повредило бы.
     
    1 person likes this.
  6. ErrorNeo

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

    Joined:
    2 May 2009
    Messages:
    923
    Likes Received:
    838
    Reputations:
    402
    прошло 1 год и 5 месяцев как я написал этот сурс... омг, как быстро время летит.

    Чтож, супиркодиром я так и не стал, но скиллы подкчал, так что отвечу на кое-какую критику, об обоснованности которой полтора года назад я еще не мог судить:

    на любителя, вопрос удобства. При небольших обьемах кода мне удобнее когда всё в 1 месте.

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

    =================================

    А теперь по существу:
    А вот тут я был неправ:
    Code:
    const 
    conn_delay=100;
    conn_retry=10;
    send_delay=3000;
    
    var 
    err_count:integer;
    label repeat_send;
    Code:
      
         repeat_send:
    
         s:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
         FillChar(addr, SizeOf(sockaddr_in), 0);
         addr.sin_family:=AF_Inet;
         addr.sin_port:=htons(80);
         addr.sin_addr.S_addr:=inet_addr('127.0.99.11');
    
        {коннектимся}
         err_count:=0; 
         while ((Connect(S,addr,SizeOf(TSockAddr))<>0)and(err_count<conn_retry)) do 
         begin        
              inc(err_count);
              sleep(conn_delay);
         end;
         closesocket(s);
    
         if err>=connect_retry then goto repeat_send;
         
    вот так вот замороченно и трехэтажно должен выглядеть правильный пацанский connect.
    127.0.99.11 тут - ip к которому собсна конектимся.

    А пацанское получение ответа должно выглядеть так:
    Code:
           
            err_count:=0;     
            while ((pos('</http>',reply)=0) and (error_count<reply_retry)) do
            begin
               inc(err_count);
               sleep(send_delay);
               reply:=reply+recvdata(s);
            end;
            closesocket(s);
    
           if err_count>=reply_retry then goto repeat_send;
    // </http> тут - "признак" конца загружаемой страницы. Можно было бы правда это делать "по-научному", но так по-моему "проще".-)

    причина: в многопоточных приложениях, когда нагрузка на сеть превышает её возможности (нередко, когда программа работает во много тысяч потоков) отсутствие коннекта, отсутствие ответа от сервера или же неполный ответ - совершенно нормальные вещи. И это необходимо обрабатывать ("бороться" с этим) коль скоро вы не хотите, чтобы ваша программа дейститвельно использовата ресурсы, предоставляемые вашей сетью на 100%.

    ps. с вышеуказанными модификациями Ваш софт начнет работать "стабильно" не только в 100 потоков, но и в 5.000.

    Странно, что никто не сделал мне такого замечания полтора года назад.)
     
    #26 ErrorNeo, 13 Feb 2011
    Last edited: 13 Feb 2011
  7. GhostOnline

    GhostOnline Active Member

    Joined:
    20 Dec 2008
    Messages:
    723
    Likes Received:
    110
    Reputations:
    22
    Не понял какбэ..
    это не только в многопоточных программах, но и всегда при работе через прокси/соксы также верно. даже если сеть загружена не полностью.
    и если прогер не проверяет корректность и вообще наличие ответа - то он просто напросто идиот. если пытаться обрабатывать такие "данные" без проверки - нить выполнения программы может завести куда угодно, программа будет глючить и вообще будет вести себя непредсказуемо.
    лично я проверяю ответ абсолютно после каждого запроса - и если фэйл то вызывается соответствующее событие, и в досье этого прокси записывается что эта прокси - редиска.

    // да, помню по этим сорцам смотрел как создавать многопоточные проги на дельфи =)
     
    #27 GhostOnline, 13 Feb 2011
    Last edited: 13 Feb 2011
  8. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Я вообще не могу понять зачем используются на прямую сокеты, раз используешь VCL, то зачем писать велосипеды.

    А вообще
    [​IMG]
     
  9. ErrorNeo

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

    Joined:
    2 May 2009
    Messages:
    923
    Likes Received:
    838
    Reputations:
    402
    если ты не понимаиш, это не значит что ты не понимаиш правильно - не забывай.

    Я бы посмотрел, как бы ты переписал этот самолет с использованием "компонент для работы с сетью" так, чтобы он безглючно взлетел хотя в 2000 потоков, и при этом имел скорость обработки запросов хотя бы равную 80% от того что будет тут.

    Тут даже изменение внутренних параметров оной функции recvdata дает +-15% производительности программы, если она работает в более чем 1000 потоков.

    А вот если полностью отказаться от VCL во всем остальном, кроме сетевых запросов - это уже, в свою очередь, не даст никаких преимуществ, потому как именно запросы - "узкое" место, и к сожалению остается им хоть на VCL хоть на WinApi.
     
    #29 ErrorNeo, 15 Feb 2011
    Last edited: 15 Feb 2011
  10. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    fd00ch, объясни конкретнее - что, где и почему?
     
  11. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    2000 тыс. потоков?! Ни как...XP не потяент потому что столько потоков врятли создастся, у меня лично создается ровно 2000 потоков, дальше не хватка памяти, но допустим у вас создастся столько(у вас и памяти больше и не XP), тут уже врятли столько TCP соединений создастся, я не знаю ограничение в Windows Server на количество соединений, но уверен что столько даже для прокси чекера многовато, короче бред.

    Хорошо, с производительностью? Ты не используешь Indy и прочую лабуду...А почему ты используешь TThread? Я вот только что написал простую прогу - создание 2000 потоков на API гораздо быстрее получилось чем при создании через TThread(это естественно). Да и не на 15% будет выгода, а гораздо гораздо меньше, самое узкое место как раз запрос, на него больше времени уходит и тут ни как не оптимизируешь.

    И кстати на Indy и на 4000 сделаю если бы была бы возможность со стороны видны. Если посмотреть исходники, то связь всех созданных компонентов Indy есть только в одном месте, которое помещено в критическую секцию, так и почему же я на столько не создам без глюков?
     
  12. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    fd00ch, не только в делфи 1мб по умолчанию.
    Через CreateThread вторым параметром указывается размер стека, а как это сдеалать для TThread?
     
  13. GhostOnline

    GhostOnline Active Member

    Joined:
    20 Dec 2008
    Messages:
    723
    Likes Received:
    110
    Reputations:
    22
    M_script размер стека под поток настраивается в параметрах проекта. странно что ты этого не знаешь.
     
  14. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Я знаю, ставил меньше - бессмыслено, создает так же ровно 2000 потоков.
     
  15. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    fd00ch, Что за винда?
     
    #35 Jingo Bo, 16 Feb 2011
    Last edited: 16 Feb 2011
  16. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    GhostOnline, я имел ввиду для конкретных потоков. В параметрах проекта настраивается сразу для всех потоков программы.
     
  17. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Я походу без того флага просто создавал потоки($00010000), вот и не учитывалось значение.
     
  18. GhostOnline

    GhostOnline Active Member

    Joined:
    20 Dec 2008
    Messages:
    723
    Likes Received:
    110
    Reputations:
    22
    А ну тогда только вышеописанным хаком. Или скопировать класс целиком в другой модуль, и подправить вызов BeginThread. Хотя я не понимаю в каких случаях может потребоваться выставлять потокам разный размер стека.
     
  19. ErrorNeo

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

    Joined:
    2 May 2009
    Messages:
    923
    Likes Received:
    838
    Reputations:
    402
    можно выставлять размер стека потоков флагом
    {$M 16384, 16384}
    сразу после объявления глобальных переменных.
    На 2 гигабайтах ОЗУ я с этим флагом запускал софт в 15.000 потоков и он нормально работал. Хотя смысла это не имеет, т.к. XP-SP3 физически не держит больше ~3500 одновременно открытых сокетов, а потому и софт, даже если он шлет "пустые" запросы - все равно не получит выигрыша в скорости при более чем 3500 потоках, если его узкое место - работа с сетью, а не вычисления.

    Что касается говнокода в моем примере, то
    1. репа ТС'а - к кодингу отношение имеет минимальное. Если 10-15 плюсов за кодинг есть - и то хорошо.
    2. я придерживаюсь исключительно практического подхода к программированию. Единственный критерий, который я принимаю и уважаю в критике - практическая (не)эффективность и возможные побочные эффекты.

    если ты, fd00ch, видишь, как можно заметно увеличить скорость работы данной программы на "нормальной" машине с 2 гигами ОЗУ, вменяемым процессором и в 2000+ потоков (а так же с выставленым размером стека, в примере я это опускал) - чтож, приведи пример.
    Это вовсе не подкол, я с удовольствием посмотрю на интересный хек, который повысит работу с маловесными запросами многопоточного приложения, не ограниченного процессорной мощностью.

    Если же всё, что ты сможешь - переписать более "сложно для понимания масс", но ничуть не более эффективно в реальных условиях - тогда увы.

    Чеккер прокси под ВК правда сегодня уже не так уместен, но ты, fd00ch, мог бы, скажем, наваять многопоточную запрашивалку стартовой страницы Яндекса так, чтобы она получила больше страниц в 10 минут, чем аналогичная, написанная моими методами.
    Что может быть проще? ;)
     
    #39 ErrorNeo, 1 Mar 2011
    Last edited: 1 Mar 2011
  20. TC-неадекват

    Joined:
    28 Mar 2011
    Messages:
    2
    Likes Received:
    0
    Reputations:
    -5
    При компиляции выдаёт ошибку в этой строке:
    addr.sin_addr.S_addr:=inet_addr(PChar(ip));