ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [python] 채팅 프로그램 만들기 (2)
    카테고리 없음 2022. 11. 20. 01:38

    이전 글에서 서버를 제작하였습니다. 혹시 앞의 글을 보지 않으셨다면 한 번 읽고 와주세요~ https://dhcoding.tistory.com/6

    서버를 만들었는데 사용자가 없으면 안되겠죠?

    이번 글에서는 client를 제작해보도록 하겠습니다. 

    import socket
    import errno
    import sys
    
    HEADER_LENGTH = 10
    IP = "127.0.0.1"
    PORT = 1234
    
    my_username = input("Username: ")
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((IP, PORT))
    client_socket.setblocking(False)
    
    username = my_username.encode()
    username_header = f"{len(username):<{HEADER_LENGTH}}".encode()
    client_socket.send(username_header + username)
    
    while True:
        if my_username == "reader":
            message = ''
        else:
            message = input(f"{my_username} > ")
    
        if message:
            message = message.encode()
            message_header = f"{len(message):<{HEADER_LENGTH}}".encode()
            client_socket.send(message_header+message)
        try:
            while True:
                username_header = client_socket.recv(HEADER_LENGTH) 
                if not len(username_header):
                    print("connection closed by the server")
                    sys.exit()
                username_length = int(username_header.decode().strip())
                username = client_socket.recv(username_length).decode()
    
                message_header = client_socket.recv(HEADER_LENGTH)
                message_length = int(message_header.decode().strip())    
                message = client_socket.recv(message_length).decode()
    
                print(f"{username} > {message}")
                
        except IOError as e:
            if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
                print('Reading error', str(e))
                sys.exit()
            continue
                
        except Exception as e:
            print('General error', str(e))
            sys.exit()

    코드는 다음과 같습니다. 

     

    client 코드도 server 코드와 거의 유사한데요. 먼저 사용할 때 주의해야 할 점은, 서버와 마찬가지로 IP주소입니다. IP를 바꾸지 않고 그대로 사용하면 아마 정상적으로 작동하지 않을 것입니다. IP는 서버를 작동시킬 컴퓨터와 같은 IP를 입력해줘야합니다. 이전 글에서 서버를 작동할 컴퓨터의 IP를 '192.166.0.159'로 하였습니다. 여기서도 IP = '192.166.0.159'로 해주셔야 정상적으로 작동합니다. (이 IP는 예시입니다. 이 예시와 같은 192.166.0.159를 IP로 설정하시면 안될수도 있습니다. 서버 프로그램의 IP를 찾는 방법은 이전 글에서 설명했습니다. 이전 글을 참고해주세요.)

     

    프로그램을 작동시키면 Username: 이 출력되며 입력할 수 있게 됩니다.  이곳에 입력하는 것은 채팅에서 쓰일 닉네임입니다. 

     

     

    닉네임을 daehoon으로 설정하기 위해 daehoon을 입력하였습니다. 입력 후 앤터를 치면 daehoon>이 뜨며 입력할 수 있게됩니다. 앞으로 입력하는 것들은 모두 메세지로 서버를 통해 다른 client에게 전송될 것입니다. 

     

    서버
    서버 프로그램&nbsp; 실행 모습

    닉네임을 입력하면 입력과 동시에 서버에 접속합니다. 접속되었다면 서버 프로그램의 콘솔 창에서는 접속한 client의 IP와 닉네임이 출력되며 접속되었다고 알린다. 

    DH라는 닉네임으로 새롭게 서버에 접속하면 이제 daehoon과 DH는 서로 서버를 통해 채팅이 가능해집니다.

    다음과 같이 서로 메세지를 주고받을 수 있습니다. 서로에게 안녕이라고 메세지를 보낸 모습입니다. 

    서버의 콘솔창에서는 다음과 같이 보낸 사람과 보낸 메세지가 띄워집니다. 

     

    여기서 문제가 있습니다. 문제점은 바로 전송된 메세지는 상대방에게 바로 출력되지 않는다는 것인데요. 상대방의 메세지를 확인하기 위해서는 앤터를 입력하거나 자신이 새로운 메세지를 입력하여야 합니다. 이 문제가 발생하는 원인은 프로그램의 작동 순서에 있습니다. client 프로그램은 입력을 항상 대기하고 있습니다. 입력을 하고 있는 중간에는 새로운 메세지가 출력되지 않는 것인데요.

    이 문제점을 해결하기 위해서는 여러 작업을 동시에 수행할 수 있는 threading이 있습니다. 하지만 이것 또한 문제가 발생합니다. 입력하는 중간에 상대방이 메세지를 전송할 시 입력과 함께 메세지가 깨지게 됩니다. 그래서 불편하더라도 메세지가 깨지지 않는 방향을 선택하였습니다. 

    threading을 사용하거나 다른 방법을 통해서 입출력이 가능하며 메세지도 깨지지 않는 방법을 새롭게 고안하여 고쳐봐야 할 것 같습니다. 

     

    앞으로 소켓 통신으로 다양한 걸 만들어보도록 하겠습니다!

    뭐.. 예를 들면, 멀티 게임, 원격 제어 프로그램 등등이 있겠네요! 기대해주세요!

     

     

     

    참고 자료

    https://www.youtube.com/watch?v=CV7_stUWvBQ&t=1117s

     

Designed by Tistory.