먼저 채팅방을 구현하려면 서버와 클라이언트가 필요하다. 즉, 두 명 이상이서 채팅을 주고받아야 한다.
서버측의 전체 코드부터 보자면
from socket import *
import threading
import time
def send(sock):
while True:
sendData = input('>>>')
sock.send(sendData.lower().encode('utf-8'))
def receive(sock):
while True:
recvData = sock.recv(1024)
print('Client :', recvData.decode('utf-8'))
port = 8081
serverSock = socket(AF_INET, SOCK_STREAM)
serverSock.bind(('', port))
serverSock.listen(1)
print(f'Waiting for connection to port {port}')
connectionSock, addr = serverSock.accept()
print(f'Connected on port {addr}')
sender = threading.Thread(target=send, args=(connectionSock,))
receiver = threading.Thread(target=receive, args=(connectionSock,))
sender.start()
receiver.start()
while True:
time.sleep(1)
pass
이런식으로 구성되어 있고, 이어서 클라이언트 측의 전체 코드도 살펴보자.
from socket import *
import threading
import time
def send(sock):
while True:
sendData = input('>>>')
sock.send(sendData.upper().encode('utf-8'))
def receive(sock):
while True:
recvData = sock.recv(1024)
print('Server :', recvData.decode('utf-8'))
port = 8081
clientSock = socket(AF_INET, SOCK_STREAM)
clientSock.connect(('127.0.0.1', port))
print('Conntection success!')
sender = threading.Thread(target=send, args=(clientSock,))
receiver = threading.Thread(target=receive, args=(clientSock,))
sender.start()
receiver.start()
while True:
time.sleep(1)
pass
프로그램에 대해 간단하게 설명하자면
서버측은 소켓을 생성(socket)하고 이 소켓에 주소를 할당(bind)하고 접속을 기다린다(listen).
코드로 살펴보면 아래와 같다. (포트번호는 8081로 설정함)
port = 8081
serverSock = socket(AF_INET, SOCK_STREAM)
serverSock.bind(('', port))
serverSock.listen(1)
클라이언트 쪽도 마찬가지로 소켓을 생성하지만, 이 후 바로 connect를 통해 서버측과 연결을 시도한다.
port = 8081
clientSock = socket(AF_INET, SOCK_STREAM)
clientSock.connect(('127.0.0.1', port))
(127.0.0.1은 자신의 컴퓨터를 의미한다)
연결 이후, 위에 정의한 send함수와 receive함수를 통해 메시지를 주고 받는다.
def send(sock):
while True:
sendData = input('>>>')
sock.send(sendData().encode('utf-8'))
def receive(sock):
while True:
recvData = sock.recv(1024)
print('Server :', recvData.decode('utf-8'))
여기서 인자로 받는 sock는 clientSock과 serverSock를 말하며, sock.send는 말 그대로 input을 통해 받은 데이터를 보내는데 그냥 보내는 것이 아닌 utf-8로 인코딩해서 보낸다. 받을 때는 sock.recv를 통해 받는데 이 때 sock.rece의 인자만큼 (byte) 받는다. 그 후 보낼때와 마찬가지로 utf-8로 온 데이터를 디코딩하여 받는다.
그리고 채팅을 계속해서 할 수 있게 하기위해 while문 안에 넣은 것이며,
밑의 코드는 송수신의 순서에 상관없이 동시적으로 작동하게 하기 위해 쓰레드를 사용하였다. 자세히 설명하지는 않겠다.
sender = threading.Thread(target=send, args=(clientSock,))
receiver = threading.Thread(target=receive, args=(clientSock,))
sender.start()
receiver.start()
while True:
time.sleep(1)
pass
간단하게 설명하면, target은 실행될 함수, args는 인자를 말한다. time.sleep(1)은 1초마다 반복하기 위해 사용한다.
그리고 전체 코드를 보면 서버와 클라이언트의 각 send함수를 자세히 보면 upper(), lower()함수가 사용된 걸 볼 수있는데 이는 클라이언트 -> 서버로 보낼 때는 모두 대문자로 가도록, 서버 -> 클라이언트는 소문자로 가도록 살짝 바꾼 것이다.
def send(sock):
while True:
sendData = input('>>>')
sock.send(sendData.upper().encode('utf-8')) // 클라이언트측 코드
def send(sock):
while True:
sendData = input('>>>')
sock.send(sendData.lower().encode('utf-8')) // 서버측 코드
실행 결과
서버->클라이언트로 보낼 때 소문자로 잘 변환되어 가고, 클라이언트->서버로 갈 때 대문자로 바뀌는 것을 확인할 수 있다.
이렇게 간단하게 1:1 채팅방을 구현해보았고, 다음은 채팅방 기능은 똑같지만 클라이언트가 로그인을 하고 들어가도록 구현해보려 한다.