Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 15, 2017 10:14:35

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

Создание таймера для прерывания итерации в основном потоке

количество запросов ограничивается пропускной способностью сети. https://github.com/gevent/gevent/blob/master/examples/dns_mass_resolve.py
в данном примере создается пул из 10 сокетов, после выполнения(или таймаута) создается следующий пул
http://blog.pythonisito.com/2012/08/building-tcp-servers-with-gevent.html
а здесь устанавливается лимит сервера на 10000 соединений

Отредактировано vic57 (Июнь 15, 2017 11:09:53)

Офлайн

#2 Июнь 15, 2017 15:21:02

UrfinJuice
Зарегистрирован: 2017-05-05
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Создание таймера для прерывания итерации в основном потоке

Рано я обрадовался. Тут вот какое дело.
Есть код:

 def scan(addr):
    try:
        global Host_name
        f = gevent.socket.gethostbyaddr(addr)
        Host_name = f[0]
        print(Host_name, ' - ', addr)
    except:
        pass
def scanfornames():
    x = input('Input first 3 octets of the network:(X.X.X.):')
    addrs = [x + str(i) for i in range(255)]
    jobs = [gevent.spawn(scan, addr)for addr in addrs ]
    gevent.joinall(jobs, timeout=5)
    #jobresults = [job.value for job in jobs]
    end = input('Restart scan? y / n     ')
    if end == 'y': scanfornames()
scanfornames()
Дело в том, что результат выполнения всегда разный… В виртуальной среде есть три хоста. Если задать маленький диапазон сканирования(5-10 адресов), то возвращаются все три имени. Если задать больше(20-50), начинаются проблемы, то один, то все, то ни одного. Увеличивал timeout, не помогает.
Одновременно с этим, в сети из около 30 машин большинство имен мгновенно возвращается, даже если диапазон все 254 адреса, но список этот постоянно разный…

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

п.с. Сильно не ругайте за код, дорогу осилит идущий…

Офлайн

#3 Июнь 15, 2017 17:08:21

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Создание таймера для прерывания итерации в основном потоке

А это не DNS-серверу плохеет?



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#4 Июнь 15, 2017 18:59:59

UrfinJuice
Зарегистрирован: 2017-05-05
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Создание таймера для прерывания итерации в основном потоке

PooH
А это не DNS-серверу плохеет?
Я запускал как в рабочей сети, так и в виртуальной среде на своем ноуте. Результаты и там и там скачут…

Офлайн

#5 Июнь 15, 2017 20:41:22

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Создание таймера для прерывания итерации в основном потоке

UrfinJuice в вашей ситуации уравнение как минимум из трех неизвестных: ваш скрипт, сеть, ДНС-сервер.
PooH высказал правильное предположение, вас скрипт пуляет в ДНС -сервер 254 запроса одновременно, получается эдакая миниDDOS-атака. На реальной сети все пакеты проходят через свич, который умеет бороться с таким поведением, да и сеть имеет загрузку поэтому пакеты вылетевшие одновременно приходят на ДНС-сервер с некотороым разбросом по времени. На виртуалке же у вас минимум сетевой активности, и свича по сути нет, вот ваш ДНС и прикуевает от такого напора.
+ на ДНС сервере может стоять ограничение на одновременное к-во соедиенений от одного хоста, вот часть запросов и отбрасывается.
Для начала попробуйте пулять не все скопом а пакетами по 10-25 запросов за раз с интервалом в пару десятков миллисекунд, и посмотрите как оно себя поведет. Ну и мониторте загрузку сети при работе вашего скрипта, и загрузку ДНС сервера.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Июнь 15, 2017 20:48:42)

Офлайн

#6 Июнь 16, 2017 10:39:27

UrfinJuice
Зарегистрирован: 2017-05-05
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Создание таймера для прерывания итерации в основном потоке

PEHDOM
Для начала попробуйте пулять не все скопом а пакетами по 10-25 запросов за раз с интервалом в пару десятков миллисекунд, и посмотрите как оно себя поведет.

Сделал вот что:

 import gevent
from gevent import socket
import time
def scan(addr):
    try:
        global Host_name
        f = gevent.socket.gethostbyaddr(addr)
        Host_name = f[0]
        print(Host_name, ' - ', addr)
    except:
        pass
addrs = ['192.168.198.1','192.168.198.130', '192.168.198.129', '192.168.198.131']
def scanfornames():
    jobs = [gevent.spawn(scan, addr)for addr in addrs ]
    gevent.joinall(jobs, timeout=2)
for i in range(20):
    scanfornames()
    time.sleep(0.02)
    print('----------------------greenlet done------------------------')

Скрипт запускает 4 микропотока через каждые 0.02 секунды на живые адреса. Вот какой получился резульатат. Строка ——greenlet done—– отображается после каждой иерации:

———————-greenlet done————————
WINDOWS-7 - 192.168.198.130
WINDOWS-XP - 192.168.198.129
UBUNTU - 192.168.198.131
———————-greenlet done————————
DESKTOP-SK6Q7EO - 192.168.198.1
———————-greenlet done————————
WINDOWS-7 - 192.168.198.130
WINDOWS-XP - 192.168.198.129
UBUNTU - 192.168.198.131
DESKTOP-SK6Q7EO - 192.168.198.1
WINDOWS-7 - 192.168.198.130
WINDOWS-XP - 192.168.198.129
UBUNTU - 192.168.198.131
———————-greenlet done————————


Может все-таки для моей задачи рациональнее использовать один поток для функции gethostbyaddr(), а второй для создания таймаута для этой функции?

Офлайн

#7 Июнь 16, 2017 12:22:32

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

Создание таймера для прерывания итерации в основном потоке

имхо дело тут в сети
попробуй со стандартным сокетом

 #!/usr/bin/env python
import sys
import gevent
#from gevent import socket
import socket
addrs = ['192.168.198.1','192.168.198.130', '192.168.198.129', '192.168.198.131']
def job(addr):
    try:
        url = socket.gethostbyaddr(addr)
        print addr,':',url
    except Exception as e:
        print addr,str(e)
        
for addr in addrs:
    jobs = [gevent.spawn(job,addr)]
    gevent.joinall(jobs,timeout=1)
    
sys.exit()

http://sdiehl.github.io/gevent-tutorial/#timeouts
таймаут можешь и через gevent сделать

Отредактировано vic57 (Июнь 16, 2017 13:09:50)

Офлайн

#8 Июнь 16, 2017 13:42:40

UrfinJuice
Зарегистрирован: 2017-05-05
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Создание таймера для прерывания итерации в основном потоке

vic57
имхо дело тут в сети/попробуй со стандартным сокетом
Попробовал, не знаю в чем разница, но на маленьких объемах пока заработало! Буду пробовать на больших.


Опять рано обрадовался…
На живых хостах да, работает. Определяет стабильно.

Но если вместо живых адресов вставить диапазон, например 10 машин, три из которых живые, то опять ответ от неживых хостов идет 4-5 секунд….. с чего и начиналось….. Я не могу понять как это работает, ведь мы запускаем 10 потоков, а ведет себя программа как-будто адреса последовательно резолвятся…..

Отредактировано UrfinJuice (Июнь 16, 2017 14:06:27)

Офлайн

#9 Июнь 16, 2017 15:28:08

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

Создание таймера для прерывания итерации в основном потоке

стандартный сокет так и должен
попробуй последовательно

 #!/usr/bin/env python
import sys
import gevent
from gevent import socket
addrs = []
urls = ['www.google.ru',
        'www.yandex.ru',
        'www.python.su',
        'www.ya.ru',
        'www.youtube.com'
        ]
def job(url):
    try:
        ip = socket.gethostbyname(url)
        print url,ip
        addrs.append(ip)
    except Exception as e:
        print url ,e
def job2(ip):
    try:
        url = socket.gethostbyaddr(ip)
        print ip,url[0]
    except Exception as e:
        print ip ,e
    
        
for url in urls:
    gevent.spawn(job,url).join(timeout=1)
    
for addr in addrs:
    gevent.spawn(job2,addr).join(timeout=1)
sys.exit()

Офлайн

#10 Июнь 16, 2017 17:54:16

UrfinJuice
Зарегистрирован: 2017-05-05
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Создание таймера для прерывания итерации в основном потоке

vic57
стандартный сокет так и должен
попробуй последовательно
Пробую на своей виртуалке код, что вы написали. Вместо урлов - свои машины. Опять то два, то три, то вообще нет результатов…. Ну здесь, правда, может из-за того, что я сам себе ДНС и одновременные запросы просто мешают друг-другу. Можно было бы забить на виртуалку, раз в промышленной среде все работает, но при маленьком количестве потоков и большем таймауте имя живого сервера тоже через раз определяется..

А если у адреса нет соотв. имени хоста, то опять, ошибка host not found, выдается оооочень долго. Вся суть этой задачи и заключается в том, чтобы сократить это время.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version