수업시간에 배운 내용들을 토대로 하여 작은 프로그램을 하나 만들어 보았다.
프로그램은 GUI 멀티 채팅 프로그램이며, Tkinter와 스레드, 소켓 라이브러리를 활용하여 구현했다.
위 세 라이브러리를 실제로 사용한 것은 이번이 처음이지만, 프로그램을 완성시키기 위해 이것 저것 검색해보고 분석하다보니 금방 적응할 수 있었다.
소스를 살펴보자~!
<server>
import socket, threading class Room: # 채팅방 클래스. def __init__(self): self.clients = [] self.allChat=None def addClient(self, c): # c: 텔레마케터 . 클라이언트 1명씩 전담하는 쓰레드 self.clients.append(c) def delClient(self, c): self.clients.remove(c) def sendMsgAll(self, msg): # 채팅방에 있는 모든 사람한테 메시지 전송 for i in self.clients: print(i) i.sendMsg(msg) class ChatClient: # 텔레마케터 def __init__(self, r, soc): self.room = r # 채팅방. Room 객체 self.id = None # 사용자 id self.soc = soc # 사용자와 1:1 통신할 소켓 def readMsg(self): self.id = self.soc.recv(1024).decode() msg = self.id + '님이 입장하셨습니다' self.room.sendMsgAll(msg) while True: msg = self.soc.recv(1024).decode() # 사용자가 전송한 메시지 읽음 if msg == '/stop': # 종료 메시지이면 루프 종료 self.soc.sendall(msg) # 이 메시지를 보낸 한명에게만 전송 self.room.delClient(self) break msg = self.id+': '+ msg self.room.sendMsgAll(msg) # 모든 사용자에 메시지 전송 self.room.sendMsgAll(self.id + '님이 퇴장하셨습니다.') def sendMsg(self, msg): print(type(msg)) self.soc.sendall(msg.encode(encoding='utf-8')) class ChatServer: ip = 'localhost' # or 본인 ip or 127.0.0.1 port = 9999 def __init__(self): self.server_soc = None # 서버 소켓(대문) self.room = Room() def open(self): self.server_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server_soc.bind((ChatServer.ip, ChatServer.port)) self.server_soc.listen() def run(self): self.open() print('서버 시작11') while True: client_soc, addr = self.server_soc.accept() print(addr, '접속') c = ChatClient(self.room, client_soc) self.room.addClient(c) print('클라:',self.room.clients) th = threading.Thread(target=c.readMsg) th.start() self.server_soc.close() def main(): cs = ChatServer() cs.run() main()
<client>
import threading import socket import tkinter as tk class UiChatClient: # class 변수 / static 변수 : 모든 객체가 공유 ip = 'localhost' port = 9999 def __init__(self): self.conn_soc = None # 서버와 연결된 소켓 self.win = None self.chatCont = None self.myChat = None self.sendBtn = None self.allChat ='' def conn(self): self.conn_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.conn_soc.connect((UiChatClient.ip, UiChatClient.port)) def setWindow(self): self.win = tk.Tk() self.win.title('채팅프로그램') self.win.geometry('400x500+100+100') self.chatCont = tk.Label(self.win, width=50, height=30, text='dd') self.myChat = tk.Entry(self.win, width=40) self.sendBtn = tk.Button(self.win, width=10, text='전송') self.chatCont.grid(row=0, column=0, columnspan=2) self.myChat.grid(row=1, column=0, padx=10) self.sendBtn.grid(row=1, column=1) self.myChat.bind('<Return>', self.sendMsg) def sendMsg(self, e): # 키보드 입력 받아 상대방에게 메시지 전송 msg = self.myChat.get() self.myChat.delete(0, tk.END) self.myChat.config(text='') print(type(msg)) msg = msg.encode(encoding='utf-8') print(self.conn_soc) self.conn_soc.sendall(msg) print('전송') def recvMsg(self): # 상대방이 보낸 메시지 읽어서 화면에 출력 print('리드') while True: print('리드') msg = self.conn_soc.recv(1024) print(msg) msg = msg.decode()+'\n' self.allChat += msg print(',:', self.allChat) self.chatCont.config(text=self.allChat) # if msg == '/stop': # self.close() # break def run(self): self.conn() self.setWindow() th2 = threading.Thread(target=self.recvMsg) th2.start() self.win.mainloop() def close(self): self.conn_soc.close() print('종료되었습니다') def main(): conn = UiChatClient() conn.run() main()
<실행 화면>
3개의 클라이언트를 띄워놓고 실행하였다.
디자인적으로는 미숙하지만 기능상 전혀 문제가 없다ㅎㅎ
![](https://blog.kakaocdn.net/dn/cmpVh6/btqQss0SaiA/T0qMxI1NgiBupkfiJtSrAk/img.png)
<깨달음>
각각의 라이브러리들이 조각조각 모여 퍼즐처럼 전체 프로그램을 완성시키는 모습에, 좀 더 규모가 큰 실 운영 프로그램은 더욱 많은 라이브러리를 필요로 할 것이라는 생각을 하였다. 그러므로 다양한 라이브러리를 접하고 익혀야 겠다는 생각을 하였다.
'프로그래밍 > 파이썬' 카테고리의 다른 글
파이썬 스레드 (Thread) (0) | 2020.12.17 |
---|---|
계산기 프로그램 TKinter (0) | 2020.12.17 |
TKinter 기본 (파이썬 GUI) (0) | 2020.12.17 |
파이썬 소켓(TCP) (0) | 2020.12.15 |
제어문 - IF (0) | 2020.11.05 |
댓글