복붙노트

[PYTHON] 파이썬에서 다중 스레드 TCP 서버

PYTHON

파이썬에서 다중 스레드 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 변수가 두 번째 연결의 소켓을 참조하도록 겹쳐 쓰므로이 문제가 발생하는지 여부는 의심 스럽습니다. 나는 그것을 정정하고 어떻게 피하는가?

소켓 변수의 수가 제한된 배열을 사용하고 각 연결에 대해 각 변수를 사용하는 것 이외의 다른 방법이 있습니까?

해결법

  1. ==============================

    1.IP 주소와 포트를 사용하는 것처럼 클라이언트 양말을 스레드에 전달해야합니다.

    IP 주소와 포트를 사용하는 것처럼 클라이언트 양말을 스레드에 전달해야합니다.

    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)
    ...
    
  2. ==============================

    2.내가 오버라이드 할 수있는 멋진 클래스를 만들었습니다.

    내가 오버라이드 할 수있는 멋진 클래스를 만들었습니다.

    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
    

    여기에 예제가 있습니다.

    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()
    
  3. from https://stackoverflow.com/questions/17453212/multi-threaded-tcp-server-in-python by cc-by-sa and MIT license