Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 8, 2013 20:39:44

Galvanize
От:
Зарегистрирован: 2011-01-14
Сообщения: 67
Репутация: +  0  -
Профиль   Отправить e-mail  

Ветвление потоков (threading). Можно ли, и нужно ли?

Всем привет.
Пишу довольно специфическую программу, и уже изрядно запутался в вопросе более лаконичной реализации.
Суть в следующем:
имеется список выделенных серверов, на которые требуется зайти , подключиться телнетом на слушающий порт своего хоста, и отключиться.

Питон скрипт, который это все реализует должен работать так:
- получает список серверов с учетными записями вида IP:login@password
- создает несколько потоков (5 например), каждый из которых должен:
—- принять определенную часть записей из списка (например, имея 100 записей в файле, каждый поток получит по 20 записей для обработки)
—- открыть слушающий порт (номер порта для каждого потока свой, чтобы избежать одновременного подключения нескольких серверов. Хотя, тут ещё нужно подумать. Возможно, что если один подключиться, второй будет ждать пока порт освободится, в чем я сомневаюсь). Сама функция прослушки будет ждать подключения, и как только оно произойдет, записывает адрес подключившегося сервера, и разрывает соединение. Потом создает его вновь, чтобы принять новое подключение от другого сервера.
—- вызвать стороннюю программу с параметрами вида IP, login, password плюс команда telnet “мой хост:порт”)
—- слушалка должна ловить соединения и сохранять их в общий массив.
—- по окончанию списка полученных данных, поток “убивается”
- ну и всякие тривиальные задачи, типа сохранения подключившихся, и т.п.

И тут у меня возникли затруднения - если я слушаю порт, программа не будет выполняться дальше, пока не произойдет отключение прослушки. Код прослушки:

def listener(port): 
        HOST = ''
        PORT = port
        s = socket(AF_INET, SOCK_STREAM)
        s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        s.bind((HOST, PORT))
        s.listen(1)
        conn, addr = s.accept()
        print '[+]Connected by', addr[0]
        if addr:
            good_servers.append(addr[0])
            print 'Address added to list'
        conn.close()

Следовательно, мне нужно выносить вызов прослушки в отдельный поток, а в параллельном вызывать подключение к удаленному сервеу. В итоге получаем картину:

Убого смотрится, но в ином случае пробелы не сохраняются (не помешало бы к quote прилепить сохранение пробелов).
              |поток с listener(порт 3331)
поток 1 <
              |поток подключений (на входе 20 адресов)
...
              |поток с listener(порт 3332)
поток 2 <
              |поток подключений (на входе 20 адресов)
...
              |поток с listener(порт 3335)
поток 5 <
              |поток подключений (на входе 20 адресов)
Вопрос: правильно ли это, и если да, то возможно ли создавать в потоке ещё два потока?
И лучше ли делать так, чем создавать отдельно несколько потоков для прослушек, и отдельно потоки для подключений к серверам?
Спасибо.



Отредактировано Galvanize (Апрель 8, 2013 21:06:42)

Офлайн

#2 Апрель 9, 2013 09:32:49

agalen
От:
Зарегистрирован: 2011-03-23
Сообщения: 185
Репутация: +  17  -
Профиль   Отправить e-mail  

Ветвление потоков (threading). Можно ли, и нужно ли?

Galvanize
- создает несколько потоков (5 например), каждый из которых должен:
—- принять определенную часть записей из списка (например, имея 100 записей в файле, каждый поток получит по 20 записей для обработки)
Имеет смысл сделать очередь, из которой потоки берут по одной записи.

Galvanize
—- открыть слушающий порт (номер порта для каждого потока свой
Достаточно одного порта для слухача, а принимать соединения в цикле. Для этого нужен отдельный поток.



Офлайн

#3 Апрель 16, 2013 20:48:23

Galvanize
От:
Зарегистрирован: 2011-01-14
Сообщения: 67
Репутация: +  0  -
Профиль   Отправить e-mail  

Ветвление потоков (threading). Можно ли, и нужно ли?

agalen
Достаточно одного порта для слухача, а принимать соединения в цикле. Для этого нужен отдельный поток.
Спасибо за отличную подсказку. Это очень хороший подход, т.к. мне ещё вместо записи в массив надо организовать запись в бд. А т.к. слухач один, то он сам будет устанавливать порядок. Супер. А то при моей идее пришлось бы ещё и очереди с обращениями к бд устраивать.
Сделал так (пробный вариант с записью в массив):
#!/usr/bin/python
# -*- coding: utf-8 -*-
from socket import *
from threading import Thread
good_servers = []
class Connect(Thread):
    def __init__(self, conn, addr):
        self.conn = conn
        self.addr = addr
        Thread.__init__(self)
    def run (self):
        while True:
            print 'Connected by: ', self.addr[0]
            good_servers.append(self.addr[0])
            print 'Address added to list'
            break
        self.conn.close()
HOST = ''
PORT = 3333
s = socket(AF_INET, SOCK_STREAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR,1 )
s.bind((HOST, PORT))
s.listen()
while True:
    conn, addr = s.accept()
    Connect(conn, addr).start()
Но как завернуть это в отдельный поток, ума не приложу. Весь день занимался этим кодом, сил на понимание потоков уже не осталось =)

PS да, я впервые сталкиваюсь с сокетами и многопоточностью =)



Отредактировано Galvanize (Апрель 16, 2013 20:53:58)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version