2016-08-17 5 views
10

pisałem kod prostego klienta TCP:W jaki sposób "generować" wiele klientów TCP za pomocą wątków zamiast otwierać wiele instancji terminala i uruchamiać skrypt kilka razy?

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() 

Chciałbym wiedzieć, w jaki sposób „generować” wielu klientów TCP używając wątki zamiast otwierania wielu instancji terminalu i uruchom skrypt kilka razy.

+5

Moduł '' threading' Python może ci pomóc. Lub spróbuj "wieloprocesowości", jeśli chcesz wyrwać się z GIL (Global Interpreter Lock - lepiej Google to określenie). Jeśli używasz Pythona 3.5, powinieneś prawie zdecydowanie wypróbować 'asyncio' i tą wymyślną składnię' async def' dla definicji funkcji asynchronicznych. – ForceBru

+0

@ForceBru, dzięki. Czy możesz dać mi przykład? Używam Pythona 3.4. –

+3

po prostu zapakuj swój obecny kod do funkcji i spawnuj kilka uruchomionych wątków (coś w stylu 'threading.Thread (target = func) .start()') – ForceBru

Odpowiedz

2

Spróbuj tego: Metoda pracownika zostanie ustawiona jako cel dla wątku. Więc każdy wątek będzie używał kodu metody. Po uruchomieniu wszystkich wątków pętla for na dole będzie czekać na zakończenie wszystkich wątków.

W metodzie pracownika można używać tablic lub list danych spoza metody. Możesz więc np. Przeglądać listę adresów URL lub dołączać pobrane dane do nowej tablicy wyjściowej.

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() 
+0

dlaczego do _ in? Nie rozumiem _ –

+0

Oznacza to, że nie potrzebujesz indeksu iteracji. Podkreślenie to konwencja oznaczająca zmienną jako nieużywaną. Możesz też użyć 'i' zamiast' _' i zignorować go. – Alu

+0

@Au, dzięki! Będę studiować kod! –

0

Właśnie owinięty kod/co chcesz zrobić, do funkcji tj worker(). Następnie dodałem dodatkowy kod do odradzania się thread i ustawię funkcję worker() jako target (funkcja/praca/kod, każdy spawnowany wątek zostanie wykonany - dlatego jest to konwencja na jego nazwę worker).

th = threading.Thread(target=worker) 

Wielowątkowość wersja z was wyżej przykład może być następująca:

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() 
+0

Nie ma 'raw_input' w Pythonie 3. Zwróć uwagę na tag. – saaj

+0

poprawiłem to - dzięki –

0

Oto jedno rozwiązanie z kolejki, aby wysłać różne wiadomości.

#!/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") 
+0

W Pythonie 3 'print' nie jest już operatorem. Zwróć uwagę na tag. – saaj

+0

dzięki, kod jest raczej pseudokodem, nie testowany, ale ma pomysły, które powinny działać. –

0

Najprostszym i najbardziej pythonic sposobem jest użycie multiprocessing thread pool implementation, a następnie zadzwonić pool.map. Ta pierwsza pozwoli Ci bez wysiłku zamienić wątki na procesy, gdy zajdzie taka potrzeba. Ta ostatnia zapewni czysty interfejs ukrywania zadań synchronizacji za kulisami.

#!/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) 
Powiązane problemy