Oppure

Loading
14/07/16 11:05
macco_cl
Ciao a tutti, da poco ho iniziato a lavorare sulla programmazione Multi Thread perché ne ho necessità per un progetto che sto sviluppando, per adesso sto ancora cercando di imparare le basi della programmazione legate a questo argomento per poi cercare di applicarle al mio progetto.

Attualmente sto lavorando sui seguenti Script che ho trovato in rete e leggermente modificato.
Quello che vorrei è un Serve sempre in ascolto che possa stampare le informazioni che gli vengono inviate da N client (in questo momento 2) solo che il programma funziona perfettamente con un solo client, nel momento in cui lancio un secondo client, per un attimo i due client funzionano bene poi il primo client va in crash con questo errore:

socket.error: [Errno 32] Broken pipe

Mi potreste dare chiarimenti sul perché ottengo questo errore e in che modo posso evitarlo?

Grazie mille per il vostro aiuto

Di seguito il codice:

Server Script:

import socket
from threading import Thread
import time
from SocketServer import ThreadingMixIn


# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
    def __init__(self, ip, port):
        Thread.__init__(self)
        self.ip = ip
        self.port = port
        print "[+] New server socket thread started for " + ip + ":" + str(port)

    def run(self):
        while True:
            data = conn.recv(2048)

            if data:
                print "Server received data:", data
            else:
                print "NO Data"

            #MESSAGE = raw_input("Multithreaded Python server : Enter Response from Server/Enter exit:")
            #if MESSAGE == 'exit':
                #break
            #conn.send(MESSAGE)  # echo


# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = '0.0.0.0'
TCP_PORT = 2004
BUFFER_SIZE = 20  # Usually 1024, but we need quick response

tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
threads = []

while True:
    tcpServer.listen(4)
    print "Multithreaded Python server : Waiting for connections from TCP clients..."
    (conn, (ip, port)) = tcpServer.accept()
    newthread = ClientThread(ip, port)
    newthread.start()
    threads.append(newthread)

for t in threads:
    t.join()


Client Script (metto solo 1 client perché ovviamente il codice è lo stesso anche per l'altro)
# Python TCP Client A
import socket
import time
host = socket.gethostname()
port = 2004
BUFFER_SIZE = 2000
#MESSAGE = raw_input("tcpClientA: Enter message/ Enter exit:")

tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpClientA.connect((host, port))

#while MESSAGE != 'exit':
while True:
    tcpClientA.send("Client 1")
    time.sleep(2)
    #data = tcpClientA.recv(BUFFER_SIZE)
    #print " Client2 received data:", data
    #MESSAGE = raw_input("tcpClientA: Enter message to continue/ Enter exit:")
#tcpClientA.sent("exit")
tcpClientA.close()

aaa
14/07/16 17:36
pierotofy
Prova a spostare:

tcpServer.listen(4)


Fuori dal while (mettilo prima).
Il mio blog: piero.dev
15/07/16 8:50
macco_cl
Ti ringrazio per l'aiuto, ho provato a spostarlo solo che ora quando lancio il secondo client ottengo il seguente errore: socket.error: [Errno 41] Protocol wrong type for socket

Quello che mi è venuto in mente, ma è solo una mia supposizione, che ci potrebbe essere un problema nella gestione del canale nel senso che tutti e due i Client nello stesso istante cercano di mandare qualcosa nel canale e allora il sistema ne blocca uno dei due per evitare un deadlock.

Possibile o sono completamente fuori strada?
aaa
15/07/16 14:18
pierotofy
Ah, ogni thread deve fare riferimento alla propria connessione, non puoi condividere conn per ogni thread.

import socket
from threading import Thread
import time
from SocketServer import ThreadingMixIn
 
 
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
    def __init__(self, ip, port, conn):
        Thread.__init__(self)
        self.ip = ip
        self.port = port
        self.conn = conn
        print "[+] New server socket thread started for " + ip + ":" + str(port)
 
    def run(self):
        while True:
            data = conn.recv(2048)
 
            if data:
                print "Server received data:", data
            else:
                print "NO Data"
 
            #MESSAGE = raw_input("Multithreaded Python server : Enter Response from Server/Enter exit:")
            #if MESSAGE == 'exit':
                #break
            #conn.send(MESSAGE)  # echo
 
 
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = '0.0.0.0'
TCP_PORT = 2004
BUFFER_SIZE = 20  # Usually 1024, but we need quick response
 
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
threads = []
tcpServer.listen(4)
 
while True:
    print "Multithreaded Python server : Waiting for connections from TCP clients..."
    (conn, (ip, port)) = tcpServer.accept()
    newthread = ClientThread(ip, port, conn)
    newthread.start()
    threads.append(newthread)
 
for t in threads:
    t.join()
Il mio blog: piero.dev
15/07/16 14:55
macco_cl
Con le correzioni che mi hai apportato il codice non mi da più errori ma ottengo un output che non mi spiego, nel senso che quando a lato server vado a stampare la variabile "data" all'interno non trovo solo la stringa "Client 1" o "Client 2" ma un elenco variabile di "Client 1" o "Client 2" come mai? La mia domanda non è legata soltanto al funzionamento del codice ma vuole essere una domanda per capire bene il funzionamento dei Thread, visto che ho iniziato a lavorarci da poco.
aaa
15/07/16 19:09
pierotofy
Un thread ti permette di cominciare un'esecuzione parallela di codice.

--- Thread 1 --- "Server received data:", data (dal Client 1)
/
Server ---
\
--- Thread 2 --- "Server received data:", data (dal Client 2)


L'istruzione:

print "Server received data:", data


Viene eseguita in parallelo, quindi è normale che avrai un alternarsi di "Client 1" e "Client 2" (non necessariamente in ordine).

Cerca "Thread" su Wikipedia.
Ultima modifica effettuata da pierotofy 15/07/16 19:11
Il mio blog: piero.dev
18/07/16 9:15
macco_cl
Scusa ma mi sono espresso male, non volevo dire che le stringhe vengono stampate in modo alterno, il mio tipo di output è una cosa del genere:

Esempio di Output che ottengo lanciando solo il client 1:

Server received data: Client1 Client1 Client1 Client1 Client1 Client1 Client1 Client1 Client1 Client1

la lunghezza di questo output è variabile, non appena mando in esecuzione il secondo client ottengo la stessa cosa solo con la stringa Client2 e non mi compare nemmeno più alcun output del Client 1.
aaa
18/07/16 13:17
pierotofy
Ah, si, assicurati di fare riferimento alla giusta variabile "conn" nel client:

    def run(self):
        while True:
            data = self.conn.recv(2048)


Altrimenti referenzi l'ultima "conn" accettata.
Il mio blog: piero.dev