wanna be dev 🧑‍💻

Cool 하고 Sick한 개발자가 되고 싶은 uzun입니다

A.K.A. Kick-snare, hyjhyj0901, h_uz99 solvedac-logo

Computer Science/Computer Network

간단한 클라이언트-서버 소켓 채팅 💬 프로그램 만들어보기 (with 파이썬🐍)

Kick_snare 2022. 10. 6. 23:00
728x90

학교 과제로 간단한 소켓 통신 채팅 프로그램 만들기가 나왔는데 한김에 포스팅하도록 하겠다.

파이썬으로 초간단 소켓 채팅 프로그램 구현

1. 과제 목표

  • 소켓을 사용하여 서버-클라이언트 간 채팅 프로그램 제작
  • 파이썬을 이용하여 서버와 클라이언트를 구현
  • TCP로 통신하여 연결이 유지 되도록 함

2. 클라이언트 구현 코드

from socket import *

print('--- Socket TCP communication client ---')

serverName = '127.0.0.1'
serverPort = int(input('enter the server port number : '))

clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))

print(f'--- connected with server {serverName}:{serverPort} ---')
while True:
    message = input('client >>> ')
    clientSocket.send(message.encode('utf-8'))
    response = clientSocket.recv(1024)
    print ('server <<<', response.decode('utf-8'))

clientSocket.close()

TCP 소켓 통신을 하는 클라이언트를 구현한다. 2, 3번 줄에서, 로컬에서 서버 를 실행할 예정이므로 서버이름을 ‘127.0.0.1’, 그리고 유저 입력으로 포트 번호를 입력받는다.

그리고 8번줄에서 기본 모듈 socket에서 불러온 socket()으로 클라이언트 소 켓을 생성해준다. 인자로 들어가는 값은 소켓의 family와 type을 지정하는 것 인데 IPv4와 TCP 통신을 위한 스트림 소켓임을 의미한다. 그 후 9번 줄에서 해당 이름과 포트 번호의 서버에게 소켓 연결을 요청한다.

이상이 없다면 연결 문구가 출력되고 while 문을 무한 반복하게 된다.
13, 14 번 줄에서는 클라이언트 유저의 입력을 받아 ‘utf-8’의 형식으로 인코딩하여 해당 소켓으로 메시지를 전송한다. UDP가 아니므로 주소를 포함하지 않는다. 그 후 15, 16번 줄에서는 서버에서 온 메시지를 받아 마찬가지로 ‘utf-8’의 형식으로 디코딩하여 콘솔에 출력하는 식으로 통신한다

3. 서버 구현 코드

from socket import *

print('--- Socket TCP communication server ---')

serverPort = 8080
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen()

print("The server is ready to receive")

connectionSocket, addr = serverSocket.accept()
print(f'--- connection start with {addr} ---')

while True:
    response = connectionSocket.recv(1024)
    print ('client <<<', response.decode('utf-8'))

    message = input('server >>> ')
    connectionSocket.send(message.encode('utf-8'))

connectionSocket.close()

TCP 소켓 통신을 하는 서버를 구현한다. 프로그램이 시작되면 서버 포트를 정하고 클라이언트와 마찬가지로 소켓을 생성한다. IPv4이며 스트림 소켓이다.

7~12번 줄은 클라이언트 코드와 다르게 소켓 연결을 요청하는 것이 아닌 연결 을 받기 위한 코드이다. 7번 줄의 bind 함수는 생성된 소켓과 AF(Address Familly, 주소체계)를 연결해주는데, 빈문자열과 포트 번호를 튜플로 넘겨주고 있다. 빈 문자열이 들어가면 모든 인터페이스와 연결가능하다는 의미이다.

9번 줄에서는 listen 메소드를 사용한다. 이를 통해서 서버 프로세스는 상대방 (클라이언트)의 접속이 올 때까지 계속 대기하는 상태가 된다. 이 함수의 인자 로 정수값을 줄 수 있는데, 이는 해당 소켓이 총 몇 개의 동시 접속을 허용하 는가를 의미한다. 위 코드에서는 값을 주지 않아 파이썬 임의의 숫자로 한다.

클라이언트 코드의 9번 줄과 같이 연결이 서버에 요청되면 서버는 그 연결 요 청을 수락 할 수 있어야한다. 이는 위 서버 코드의 12번 줄에서 accept 함수 를 이용하여 동작한다. 이 때 새로운 소켓과 상대방의 주소(AF)가 반환되는데, 기존 서버 소켓과 다른 새로운 소켓임을 유의해야한다.

15~20번 줄에서는 이 새로운 소켓을 이용하여 클라이언트와 통신하게 된다. 순서는 다르지만 클라이언트 코드와 마찬가지로 ‘utf-8’의 형식으로 인코딩, 디코딩하여 채팅 메세지를 입출력 받는다.

4. 실행 결과

클라이언트 프로세스와 서버 프로세스가 TCP로 연결되어 채팅을 하고 있는 모습이다. 클라이언트에서 서버 포트 번호 8080을 입력하고 연결을 요청하자, 서버는 그 연결을 수락하고 채팅이 시작된다.

5. 한계점과 발전방향

위 채팅 프로그램은 클라이언트-서버 간의 채팅을 구현하였지만 둘 중 한 호스트가 메시지를 한번 보내고 나면 상대방의 메시지를 받기 전까지는 다시 메시지를 보낼 수 없다.

while 문으로 무한 반복하여 유저 입력, 상대방 메시지 를 계속 기다리고 있기 때문이다. 이를 해결하기 위해서는 멀티 쓰레드를 이용 한다면 해결할 수 있을 것으로 보인다.

또한 연결이 실패했을 경우는 생각하고 있지 않아 프로세스가 종료될 수 있다. exception으로 요청 서버가 존재하지 않는 경우 등의 예외 처리를 한다면 보다 견고한 프로그램이 될 것이다.

728x90