Как "сгенерировать" несколько клиентов TCP с помощью потоков, вместо того чтобы открывать несколько экземпляров терминала и запускать script несколько раз?

Я написал код для простого клиента TCP:

from socket import *

# Configurações de conexão do servidor
# O nome do servidor pode ser o endereço de
# IP ou o domínio (ola.python.net)
serverHost = 'localhost'#ip do servidor
serverPort = 50008

# Mensagem a ser mandada codificada em bytes
menssagem = [b'Ola mundo da internet!']

# Criamos o socket e o conectamos ao servidor
sockobj = socket(AF_INET, SOCK_STREAM)
sockobj.connect((serverHost, serverPort))

# Mandamos a menssagem linha por linha
for linha in menssagem:
    sockobj.send(linha)

    # Depois de mandar uma linha esperamos uma resposta
    # do servidor
    data = sockobj.recv(1024)
    print('Cliente recebeu:', data)

# Fechamos a conexão
sockobj.close()

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

Ответ 1

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

В рабочем методе вы можете использовать массивы или списки данных вне метода. Таким образом, вы можете итерировать, например, по списку Urls или добавить полученные данные в новый выходной массив.

import threading

threads = []
maxNrOfThreads = 5

def worker():
    do_stuff()

for _ in range(maxNrOfThreads):
    thr = threading.Thread(target=worker)
    threads.append(thr)
    thr.setDaemon(True)
    thr.start()

for thread in threads:
    thread.join()

Ответ 2

Я только что завернул ваш код/​​то, что вы хотите сделать, в функцию i.e. worker(). Затем я добавил дополнительный код для thread spawning и установил worker() как функцию target (будет выполняться функция/работа/код каждого порожденного потока - вот почему это соглашение, чтобы назвать его worker).

th = threading.Thread(target=worker)

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

import threading
from socket import *

serverHost = 'localhost'#ip do servidor
serverPort = 50008

threads = []
input = input("Enter the number of threads:")
num_of_threads = int(input)

def worker():
    # Criamos o socket e o conectamos ao servidor
    sockobj = socket(AF_INET, SOCK_STREAM)
    sockobj.connect((serverHost, serverPort))

    # Mandamos a menssagem linha por linha
    for linha in menssagem:
        sockobj.send(linha)
        # Depois de mandar uma linha esperamos uma resposta
        # do servidor
        data = sockobj.recv(1024)
        print('Cliente recebeu:', data)

    sockobj.close()

# thread generation block
for t in range(num_of_threads):
    th = threading.Thread(target=worker)
    threads.append(th)
    th.setDaemon(True)
    th.start()

for thread in threads:
    thread.join()

Ответ 3

Вот одно решение с очередями отправки отдельных сообщений.

#!/usr/bin/python

import Queue
import threading
import time
from socket import *


DEF_HOST = 'localhost'
DEF_PORT = 50008


queueLock = threading.Lock()


class myThreadTCP (threading.Thread):

    def __init__(self, host=DEF_HOST, port=DEF_PORT, q=None):
        threading.Thread.__init__(self)
        self.host = host
        self.port = port
        self.q = q

    def run(self):
        global queueLock
        print("Starting Thread")
        # Criamos o socket e o conectamos ao servidor
        sockobj = socket(AF_INET, SOCK_STREAM)
        sockobj.connect((self.host, self.port))
        while not workQueue.empty():
            with queueLock:
                data = q.get()
            if data:
                print("sending %s" % data)
                sockobj.send(data)
                # Depois de mandar uma linha esperamos uma resposta
                # do servidor
                data = sockobj.recv(1024)
                print('Cliente recebeu:', data)
        # Fechamos a conexão
        sockobj.close()
        print("Exiting Thread")


workQueue = Queue.Queue()

# Mensagem a ser mandada codificada em bytes
menssagem = [b'Ola mundo da internet!', b'Ola mundo da internet #2!']
for msg in menssagem:
    workQueue.put(msg)

threads = []

# Create 10 new threads
for i in range(0, 10):
    thread = myThreadTCP(host=DEF_HOST, port=DEF_PORT, q=workQueue)
    thread.daemon = True
    thread.start()
    threads.append(thread)

# Wait for all threads to complete
for t in threads:
    t.join()
print("Exiting Main Thread")

Ответ 4

Простейший и самый pythonic способ использовать многопроцессорную реализацию пула потоков, а затем вызывать pool.map. Первый позволит вам без проблем переходить от потоков к процессам, когда это необходимо. Последний предоставит вам чистый интерфейс, скрывающий операции синхронизации за кулисами.

#!/usr/bin/env python3 


import socket
from pprint import pprint
from contextlib import closing
from multiprocessing.dummy import Pool as ThreadPool


serverHost = 'localhost'
serverPort = 80


messageGroups = [
    [b'GET / HTTP/1.0\n\n'],
    [b'GET /some-path HTTP/1.0\n\n'],
]

def send(messages):
    result = []
    options = socket.AF_INET, socket.SOCK_STREAM
    with closing(socket.socket(*options)) as sockobj:
        sockobj.connect((serverHost, serverPort))
        for message in messages:
            sockobj.send(message)
            response = sockobj.recv(1014)
            result.append((message, response))

    return result


if __name__ == '__main__':
    size = 10
    pool = ThreadPool(size)
    result = pool.map(send, messageGroups)
    pool.close()
    pool.join()

    pprint(result)