Python - socketserver와 threading을 이용한 채팅서버 구축

import socketserver, threading, socket


class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request.recv(1024).decode()
        cur_thread = threading.current_thread()
        response = "{}: {}".format(cur_thread.name, data)
        self.request.sendall(response.encode('utf-8'))

# handle함수는 클라이언트로부터 request가 왔을 때 동작하는 함수입니다.
# socketserver.BaseRequestHandler 클래스를 상속했다면 반드시 사용자가 override를 하여 실행할 동작을 정의해 주어야합니다.
# data는 클라이언트가 보낸 데이터(버퍼사이즈1024)를 보유하고 있습니다.
# 현재 쓰레드를 호출하고 이를 cur_thread라는 변수에 대입합니다.
# cur_thread.name으로 현재 쓰레드의 이름 (쓰레드 생성시 이름을 지정할 수 있으며 지정하지 않을경우 기본적으로 'Thread-정수(1부터시작)'이 기본값이 됩니다.
# 따라서 response는 현재 쓰레드 이름과 클라이언트가 수신한 데이터를 문자열로 보관하는 변수이고
# 이를 인코딩 하여 sendall메소드를 통해 접속한 모든 클라이언트에게 보내주게 됩니다.

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass
# socket서버의 ThreadingMixIn클래스와 TCP클래스를 상속받은 새로운 클래스 ThreadedTCPServer를 새롭게 생성했습니다.
# 이제 ThreadedTCPServer는 두 클래스의 메소드를 사용할 수 있습니다.

def client(ip, port, message):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((ip, port))
    try:
        sock.send(message.encode('utf-8'))
        response = sock.recv(1024).decode()
        print("Received: {}".format(response))
    finally:
        sock.close()

# client라는 함수를 정의하며 인자로 ip, port, message를 받습니다.
# 소켓의 기본값이 되는 ipv4, TCP로 소켓을 생성하고 이를 sock 변수라고 지칭했습니다.
# 변수로 받은 ip, port에 소켓이 연결합니다.
# 이 후 변수로 받은 message를 인코딩하여 지정한 소켓으로 전송합니다 (여기서는 서버)
# 서버로부터 받은 응답을 response에 담습니다.
# 그리고 받은 데이터를 디코딩한 뒤 print합니다.
# 구문이 정상적으로 실행되면 소켓을 닫습니다. < 소켓은 항상 마지막에 닫아주어야 합니다.

if __name__ == "__main__":
    HOST, PORT = "localhost", 0
    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    ip, port = server.server_address

    # HOST와 PORT를 각각 localhost, 미사용중인 아무포트로 배정했습니다.
    # server라는 객체는 위에서 정의한 ThreadedTCPServer의 인스턴스이며, ????에게 인자를 전달합니다.
    # server_address 메소드는 ThreadedTCPServer 인스턴스의 ip와 포트를 반환합니다. 각각을 ip, port 변수에 담습니다.

    # Start a thread with the server -- that thread will then start one
    # more thread for each request
    server_thread = threading.Thread(target=server.serve_forever)
    # server_thread라는 객체를 만들었습니다. 이 쓰레드에서는 server.serve_forever라는 메소드를 실행할 것입니다.
    # serve_forever는 socketserver에 내장된 메소드로, 서버를 실행합니다.

    server_thread.daemon = True
    server_thread.start()
    print("Server loop running in thread:", server_thread.name)
    client(ip, port, "Hello World 1")
    client(ip, port, "Hello World 2")
    client(ip, port, "Hello World 3")
    server.shutdown()
    server.server_close()



이해가 안되는 것....

- handle 메소드에 왜 쓰레드를 넣는것인지 이해가 잘 안됩니다.
- 여기서 서버 실행은 서브쓰레드가 하는건가요?
- server 인스턴스는 (HOST,PORT), ThreadedTCPRequestHandler 인자를 누구한테 주는건가요??
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass
.
.
.
    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)

이 구문이요

댓글

이 블로그의 인기 게시물

로컬 Tomcat 서버 실행속도 개선

2019.05.23 - SQLAlchemy 의 객체 상태 관리 (expire, refresh, flush, commit) 에 관한 이해

2020.02.17 Python의 multiprocessing 중 Pool.map(), chunksize에 관한 내용