2013-07-03 18 views
16

Stworzyłem prosty, wielowątkowy serwer tcp, wykorzystując moduł tnący Pythona. Ten serwer tworzy nowy wątek za każdym razem, gdy nowy klient jest podłączony.Serwer wielojęzykowy TCP w języku 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() 

Następnie otworzyłem dwa nowe terminale i połączono z serwerem przy użyciu netcat. Następnie, po wpisaniu i wysłaniu moich pierwszych danych do serwera przy użyciu pierwszego terminalu, który podłączyłem, odpowiedź z serwera przychodzi na drugi terminal, a pierwsze połączenie zostaje odłączone. Zgadłem powód, ale mam wątpliwości, czy tak się dzieje, ponieważ zmienna clientock jest zmieniona tak, że odnosi się do gniazda drugiego połączenia. Czy mam rację, a następnie, jak tego uniknąć?

Czy istnieje sposób inny niż użycie tablicy z ograniczoną liczbą zmiennych gniazda i użycie każdej zmiennej dla każdego połączenia?

+3

Nie martw się, to jest dobre pytanie. Witamy w StackOverflow! – Jordan

+0

Wygląda na to, że nigdy nie docierasz do dwóch ostatnich linii. Czy to jest zamierzone? –

Odpowiedz

13

Należy zdać skarpetkę klienta do wątku, jak to zrobić przy użyciu adresu IP oraz port:

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

Dziękuję! To działało ładnie. Dzięki. :) – Deepal

+0

Używam Pythona 2.7. Wprowadziłem zalecane zmiany, ale po podłączeniu drugiego klienta netcat pierwszy klient zawiesił się. Nie bardzo rozumiem, co się dzieje. Ktoś jeszcze ma ten problem? – John

0

I stworzyliśmy tę przyjemną klasę można zastąpić

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 

A oto przykład:

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