2013-07-03 3 views
16

나는 파이썬의 쓰레드 모듈을 사용하여 간단한 멀티 쓰레드 tcp 서버를 만들었다. 이 서버는 새로운 클라이언트가 연결될 때마다 새로운 스레드를 생성합니다.파이썬의 멀티 쓰레드 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() 

그런 다음 두 개의 새 단말기를 열고 netcat을 사용하여 서버에 연결했습니다. 그런 다음 연결 한 첫 번째 터미널을 사용하여 서버에 첫 번째 데이터를 입력하고 보내면 서버의 응답이 다른 터미널에 전달되고 첫 번째 연결이 끊어졌습니다. 그 이유는 짐작했지만 clientsock 변수가 덮어 쓰기되어 두 번째 연결의 소켓을 참조하기 때문에 이런 일이 발생하는지는 의문입니다. 나는 그것을 정정하고 어떻게 피하는가?

소켓 변수의 수가 제한되어 있고 각 연결마다 각 변수를 사용하는 배열을 사용하는 방법 외에 다른 방법이 있습니까? 여기의 나는이 좋은 클래스를 생성 한

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

마지막 두 줄에 도달하지 못하는 것 같습니다. 그게 의도적 인거야? –

답변

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

파이썬 2.7을 사용하고 있습니다. 권장 변경 사항을 만들었지 만 두 번째 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 

을 무시할 수 있습니다 그리고 :