2013-07-03 2 views
16

Ich habe einen einfachen Multithread-TCP-Server mit Python-Threading-Modul erstellt. Dieser Server erstellt jedes Mal einen neuen Thread, wenn ein neuer Client verbunden wird.Multi-Threaded TCP-Server in Python

#!/usr/bin/env python 

import socket, threading 

class ClientThread(threading.Thread): 

    def __init__(self,ip,port): 
     threading.Thread.__init__(self) 
     self.ip = ip 
     self.port = port 
     print "[+] New thread started for "+ip+":"+str(port) 


    def run(self):  
     print "Connection from : "+ip+":"+str(port) 

     clientsock.send("\nWelcome to the server\n\n") 

     data = "dummydata" 

     while len(data): 
      data = clientsock.recv(2048) 
      print "Client sent : "+data 
      clientsock.send("You sent me : "+data) 

     print "Client disconnected..." 

host = "0.0.0.0" 
port = 9999 

tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

tcpsock.bind((host,port)) 
threads = [] 


while True: 
    tcpsock.listen(4) 
    print "\nListening for incoming connections..." 
    (clientsock, (ip, port)) = tcpsock.accept() 
    newthread = ClientThread(ip, port) 
    newthread.start() 
    threads.append(newthread) 

for t in threads: 
    t.join() 

Dann habe ich zwei neue Terminals geöffnet und mit Netcat mit dem Server verbunden. Wenn ich dann meine ersten Daten über das erste Terminal, das ich angeschlossen habe, eintippe und an den Server sende, kommt die Antwort vom Server zum anderen Terminal und die erste Verbindung wurde getrennt. Ich vermutete den Grund, aber ich bin zweifelhaft, ob dies passiert, weil clientsock Variable überschrieben wird, so dass es sich auf den Socket der zweiten Verbindung bezieht. Habe ich Recht und dann wie kann ich das vermeiden?

Gibt es eine andere Möglichkeit, als ein Array mit einer begrenzten Anzahl von Socket-Variablen zu verwenden und jede Variable für jede Verbindung zu verwenden?

+3

Keine Sorge, das ist eine gute Frage. Willkommen bei StackOverflow! – Jordan

+0

Es scheint, dass Sie nie die letzten zwei Zeilen erreichen. Ist das beabsichtigt? –

Antwort

13

Sie sollten die Client-Socke auf den Thread übergeben, wie Sie mit der IP-Adresse zu tun und dem Hafen:

class ClientThread(threading.Thread): 

    def __init__(self, ip, port, socket): 
     threading.Thread.__init__(self) 
     self.ip = ip 
     self.port = port 
     self.socket = socket 
     print "[+] New thread started for "+ip+":"+str(port) 

    def run(self): 
     # use self.socket to send/receive 

... 
(clientsock, (ip, port)) = tcpsock.accept() 
newthread = ClientThread(ip, port, clientsock) 
... 
+1

Danke !! Es hat gut funktioniert. Vielen Dank. :) – Deepal

+0

Ich benutze Python 2.7. Ich habe die empfohlenen Änderungen vorgenommen, aber nach dem Verbinden eines zweiten NetCat-Clients hängt der erste Client. Ich verstehe nicht ganz, was vor sich geht. Hat noch jemand dieses Problem? – John

0

ich diese nette Klasse erstellt haben, können Sie

import socket 
import thread 

class SocketServer(socket.socket): 
    clients = [] 

    def __init__(self): 
     socket.socket.__init__(self) 
     #To silence- address occupied!! 
     self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     self.bind(('0.0.0.0', 8080)) 
     self.listen(5) 

    def run(self): 
     print "Server started" 
     try: 
      self.accept_clients() 
     except Exception as ex: 
      print ex 
     finally: 
      print "Server closed" 
      for client in self.clients: 
       client.close() 
      self.close() 

    def accept_clients(self): 
     while 1: 
      (clientsocket, address) = self.accept() 
      #Adding client to clients list 
      self.clients.append(clientsocket) 
      #Client Connected 
      self.onopen(clientsocket) 
      #Receiving data from client 
      thread.start_new_thread(self.recieve, (clientsocket,)) 

    def recieve(self, client): 
     while 1: 
      data = client.recv(1024) 
      if data == '': 
       break 
      #Message Received 
      self.onmessage(client, data) 
     #Removing client from clients list 
     self.clients.remove(client) 
     #Client Disconnected 
     self.onclose(client) 
     #Closing connection with client 
     client.close() 
     #Closing thread 
     thread.exit() 
     print self.clients 

    def broadcast(self, message): 
     #Sending message to all clients 
     for client in self.clients: 
      client.send(message) 

    def onopen(self, client): 
     pass 

    def onmessage(self, client, message): 
     pass 

    def onclose(self, client): 
     pass 

außer Kraft setzen und hier ist ein Beispiel:

class BasicChatServer(SocketServer): 

    def __init__(self): 
     SocketServer.__init__(self) 

    def onmessage(self, client, message): 
     print "Client Sent Message" 
     #Sending message to all clients 
     self.broadcast(message) 

    def onopen(self, client): 
     print "Client Connected" 

    def onclose(self, client): 
     print "Client Disconnected" 

def main(): 
    server = BasicChatServer() 
    server.run() 

if __name__ == "__main__": 
    main() 
Verwandte Themen