Найти - Пользователи
Полная версия: Ветвление потоков (threading). Можно ли, и нужно ли?
Начало » Python для новичков » Ветвление потоков (threading). Можно ли, и нужно ли?
1
Galvanize
Всем привет.
Пишу довольно специфическую программу, и уже изрядно запутался в вопросе более лаконичной реализации.
Суть в следующем:
имеется список выделенных серверов, на которые требуется зайти , подключиться телнетом на слушающий порт своего хоста, и отключиться.

Питон скрипт, который это все реализует должен работать так:
- получает список серверов с учетными записями вида 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 адресов)
Вопрос: правильно ли это, и если да, то возможно ли создавать в потоке ещё два потока?
И лучше ли делать так, чем создавать отдельно несколько потоков для прослушек, и отдельно потоки для подключений к серверам?
Спасибо.
agalen
Galvanize
- создает несколько потоков (5 например), каждый из которых должен:
—- принять определенную часть записей из списка (например, имея 100 записей в файле, каждый поток получит по 20 записей для обработки)
Имеет смысл сделать очередь, из которой потоки берут по одной записи.

Galvanize
—- открыть слушающий порт (номер порта для каждого потока свой
Достаточно одного порта для слухача, а принимать соединения в цикле. Для этого нужен отдельный поток.
Galvanize
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 да, я впервые сталкиваюсь с сокетами и многопоточностью =)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB