Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 23, 2008 14:35:07

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

Запуск и контроль процесса

Всем привет!

Есть необходимость контролировать и обмениваться данными с прокси сервером из приложения.
То есть, есть GUI с кнопками start/stop proxy. Так вот надо программно запускать прокси (сам класс прокси уже реализовал) и оставливать. При этом в самом классе прокси идет обработка данных, которые через него пропускаются и эти данные надо передать основному приложению. Загвоздка в том, что если в хендлере on_click запускать прокси (вызывать метод соответствующего объекта), то фактически приложение блокируется и ждет когда этот процесс кто-нить прибьёт.

Подскажите как правильно реализовывать подобное взаимодействие. Я так понимаю, надо в отдельный поток запускать сервер?



Офлайн

#2 Авг. 23, 2008 17:53:16

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Запуск и контроль процесса

Первую часть почти не понял.
Понял начиная с места “Загвоздка в том, что если в хендлере on_click”: да. нужно вынести в отдельный поток. Например с помощью нитей (Threading).
Вот например почитать можно для понимания:
http://www.intuit.ru/department/pl/python/11/



Отредактировано (Авг. 23, 2008 17:53:35)

Офлайн

#3 Авг. 24, 2008 00:17:16

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

Запуск и контроль процесса

shiza, спасибо. потоки то, что надо. Но это только половина проблемы.
Ещё раз попробую объяснить суть задачи :)
Есть GUI приложение, в котором необходимо запускать, обмениваться данными и останавливать прокси сервер.
То есть есть кнопки “Start Proxy” и “Stop Proxy”.
В простейшем случае (тут пока без потоков) в обработчике клика по кнопке “Start Proxy” будет что-то типа:

    
HOST_NAME = '127.0.0.1'
PORT_NUMBER = 8080
server_class = BaseHTTPServer.HTTPServer
httpd = server_class((HOST_NAME, PORT_NUMBER), ProxyHandler)
print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)
httpd.serve_forever()
Добавляем потоки и пускаем сервер в отдельный поток.
Как обмениваться нужными данными с этим запущенным сервером вроде понятно, буду отдавать ему объект-хранилище, а в ProxyHandler буду работать с этим хранилищем. Хотя может и тут будут советы?

Но вот пока что не понятно, а как собственно останавливать этот сервер, то есть что писать в обработчике “Stop Proxy” =)



Офлайн

#4 Авг. 24, 2008 00:42:44

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Запуск и контроль процесса

pento
Но вот пока что не понятно, а как собственно останавливать этот сервер, то есть что писать в обработчике “Stop Proxy”
Попробуй такой вариант:
вместо httpd.serve_forever(), написать так:
.....
#делаем таймаут на ожидание подключения (например 5), чтоб httpd.handle_request()
#не зависал намертво при отсуствеии подключений
httpd.socket.settimeout(5)
....
while 1:
if stop_command: #флаг, который надо поставить в True, когда захочется застопить сервер.
break
httpd.handle_request()



Отредактировано (Авг. 24, 2008 00:50:28)

Офлайн

#5 Авг. 24, 2008 01:04:37

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Запуск и контроль процесса

По поводу общей архитектуры.
Не очень понятно про ту часть программы, которая обменивается данными с сервером.
Она привязана к GUI?
Просто тут есть 3 варианта.
Пускать ее в потоке с GUI;
пускать в потоке сервера (как кусок в цикле сервера);
пускать в отдельном своем потоке.



Офлайн

#6 Авг. 24, 2008 01:26:46

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

Запуск и контроль процесса

О, спасибо. Про цикл я что-то сразу не догадался.

shiza
Она привязана к GUI?
Прокси сервер временно влючается из основной программы. Затем через этот прокси происходит обмен HTTP трафиком, при этом этот трафик анализируется. Так вот результаты анализа потом и надо вернуть обратно в основную программу.
Таким образом я в обработчике Start Proxy буду запускать прокси сервер отдельным потоком. И в хэндлере ProxyHandler я анализирую трафик и буду писать в какой-нить общий объект-хранилище полученные результаты, что бы в основном потоке программы была возможность оперировать этими результами. То есть потока будет два: основное GUI приложение и поток прокси сервера.



Офлайн

#7 Авг. 24, 2008 01:40:43

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Запуск и контроль процесса

Понятно.
Вообще если в GUI делать какие-нибудь длительные вычисления, то он на это время зависает и юзер начинает испытывать дискомфорт =).
Поэтому считается кошерным выносить эти самые вычисления в отдельный поток и в гуе прогресс-бар например показывать.

Если у тебя анализ трафика занимает много времени и потенциальный юзер привередлив - имеет смысл тоже так сделать =)



Офлайн

#8 Авг. 24, 2008 01:54:30

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

Запуск и контроль процесса

shiza, да нет. Там всего ничего..пара HTTP заголовков выкусываться будет. :) А прогресс бар не нужен будет. Юзер сам будет прописывать мой прокси у себя в браузере и фактически сам контролировать процесс.
Ещё раз спасибо за советы!



Офлайн

#9 Авг. 30, 2008 17:03:59

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

Запуск и контроль процесса

Кстати, таки сделал. Взаимодействие через события модуля threading =) Ещё раз спасибо за советы!
Отладочный код:

def kill_server(run_event):
print "Let's kill server!"
run_event.clear()

httpd = XcobraProxyServer()
run_event = threading.Event()
run_event.set()

p1 = threading.Thread(target=httpd.run, name="t1", args=[run_event])
p1.start()
t = threading.Timer(10.0, kill_server, [run_event])
t.start()
Соотвествующий метод класса XcobraProxyServer:
def run(self, run_event):
"""Runs server"""
self.socket.settimeout(5)
if self.verbose:
print "Starting Proxy Server on %s:%s" % self.server_address

while True:
if not run_event.isSet():
break
self.handle_request()

if self.verbose:
print "Stoping Proxy Server on %s:%s" % self.server_address



Отредактировано (Авг. 30, 2008 17:05:11)

Офлайн

#10 Авг. 30, 2008 17:20:04

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

Запуск и контроль процесса

=)



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version