2013-07-03 24 views
16

私は、PythonのThredingモジュールを使用して、単純なマルチスレッドtcpサーバーを作成しました。このサーバーは、新しいクライアントが接続されるたびに新しいスレッドを作成します。PythonのマルチスレッドTCPサーバー

#!/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() 

次に、2つの新しい端末を開き、netcatを使用してサーバーに接続しました。次に、接続した最初の端末を使用してサーバーに最初のデータを入力して送信すると、サーバーからの応答がもう一方の端末に送られ、最初の接続が切断されました。私はその理由を推測しましたが、クライアントロック変数が上書きされて2番目の接続のソケットを参照するため、これが起こるかどうかは疑問です。私は正しいですし、それを回避する方法はありますか?

ソケット変数の数が限られている配列を使用し、各接続に各変数を使用する以外の方法はありますか?ここだ、私はこの素敵なクラスを作成している

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) 
... 
+3

これは良い質問です。 StackOverflowへようこそ! – Jordan

+0

最後の2行には決して到達しないようです。それは意図的なのでしょうか? –

答えて

13

あなたは、IPアドレスとポートをどうのようにスレッドにクライアントの靴下を渡す必要があります例:

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

ありがとうございました!それはきれいに働いた。ありがとう。 :) – Deepal

+0

私はPython 2.7を使用しています。私は推奨された変更を加えましたが、2番目のnetcatクライアントを接続した後、最初のクライアントがハングします。私は何が起こっているのかよく分かりません。誰でもこの問題がありますか? – John

0

あなたは

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 

を上書きすることができそして: