728x90
2.5 채팅 서비스 만들기
2.5.1 채팅 서버 만들기
chatserver.py
import socketserver
import threading
HOST = ''
PORT = 9009
lock = threading.Lock()
class UserManager:
def __init__(self):
self.users = {}
def addUser(self, username, conn, addr):
if username in self.users:
conn.send('이미 등록된 사용자입니다.\n'.encode())
return None
# 새로운 사용자를 등록함
lock.acquire()
self.users[username] = (conn, addr)
lock.release()
self.sendMessageToAll('[%s]님이 입장했습니다.' % username)
print('+++ 대화 참여자 수 [%d]' % len(self.users))
return username
def removeUser(self, username): # 중간에 채팅방에서 나가는 사람
if username not in self.users: # 있으면 지우고 없으면 못지움
return
lock.acquire() # 락 풀기
del self.users[username] # 방금 입력받은 유저네임을 키로 해서 지움
lock.release() # 다시 락 걸기
self.sendMessageToAll('[%s]님이 퇴장했습니다.' % username)
print('--- 대화 참여자 수 [%d]' % len(self.users))
def messageHandler(self, username, msg): # 메시지 어떻게 만들어 사용할 것인지
if msg[0] != '/':
self.sendMessageToAll('[%s] %s' % (username, msg))
return
if msg.strip() == '/quit':
self.removeUser(username)
return -1
def sendMessageToAll(self, msg):
for conn, addr in self.users.values():
conn.send(msg.encode())
class MyTcpHandler(socketserver.BaseRequestHandler):
userman = UserManager()
def handle(self):
print('[%s] 연결됨' % self.client_address[0]) # 참조 받았언 BaseRequestHandler 안에 들어있음
try:
username = self.registerUsername()
msg = self.request.recv(1024)
while msg:
print(msg.decode())
if self.userman.messageHandler(username, msg.decode()) == -1:
self.request.close()
break
msg = self.request.recv(1024)
except Exception as e:
print(e)
print('[%s] 접속종료' % self.client_address[0])
self.userman.removeUser(username)
def registerUsername(self):
while True:
self.request.send('로그인ID:'.encode())
username = self.request.recv(1024)
username = username.decode().strip()
if self.userman.addUser(username, self.request, self.client_address):
return username
class ChatingServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def runServer():
print('+++ 채팅 서버를 시작합니다.')
print('+++ 채팅 서버를 끝내려면 Ctrl-C를 누르세요.')
try:
server = ChatingServer((HOST, PORT), MyTcpHandler)
server.serve_forever()
except KeyboardInterrupt:
print('--- 채팅 서버를 종료합니다.')
server.shutdown()
server.server_close()
runServer()
|
chatclient.py
import socket
from threading import Thread
HOST ='localhost'
PORT = 9009
def rcvMsg(sock): # 메시지를 받아들이는 부분
while True:
try:
data = sock.recv(1024)
if not data:
break
print(data.decode())
except:
pass
def runChat():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((HOST, PORT))
t = Thread(target=rcvMsg, args=(sock,))
t.daemon = True
t.start()
while True:
msg = input()
if msg == '/quit':
sock.send(msg.encode())
break
sock.send(msg.encode())
runChat()
|
2.6 파일 전송 프로그램 만들기
2.6.1 파일 송신 프로그램
import socketserver
from os.path import exists
HOST = ''
PORT = 9009
class MyTcpHandler(socketserver.BaseRequestHandler):
def handle(self):
data_transferred = 0
print('[%s] 연결됨' %self.client_address[0])
filename = self.request.recv(1024)
filename = filename.decode()
if not exists(filename):
return
print('파일 [%s] 전송 시작...' %filename)
with open(filename, 'rb') as f:
try:
data = f.read(1024)
while data:
data_transferred += self.request.send(data)
data = f.read(1024)
except Exception as e:
print(e)
print('전송완료[%s], 전송량[%d]' %(filename, data_transferred))
def runServer():
print('+++ 파일 서버를 시작합니다.')
print('+++ 파일 서버를 끝내려면 Ctrl-C를 누르세요.')
try:
server = socketserver.TCPServer((HOST, PORT), MyTcpHandler)
server.serve_forever()
except KeyboardInterrupt:
print('--- 파일 서버를 종료합니다.')
runServer()
|
2.6.2 파일 수신 프로그램
import socket
HOST = 'localhost'
PORT = 9009
def getFileFromServer(filename):
data_transferred = 0
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((HOST, PORT))
sock.sendall(filename.encode())
data = sock.recv(1024)
if not data:
print('파일[%s]: 서버에 존재하지 않거나 전송중 오류발생' %filename)
return
with open('download/'+filename, 'wb') as f:
try:
while data:
f.write(data)
data_transferred += len(data)
data = sock.recv(1024)
except Exception as e:
print(e)
print('파일 [%s] 전송종료. 전송량 [%d]' %(filename, data_transferred))
filename = input('다운로드 받을 파일이름을 입력하세요: ')
getFileFromServer(filename)
|
728x90
'PYTHON-BACK' 카테고리의 다른 글
#파이썬 도서관 출납 시스템_17일차 (3) | 2024.07.23 |
---|---|
#파이썬 도서관 출납 시스템_16일차 (1) | 2024.07.22 |
#파이썬 기초 15일차 (0) | 2024.07.19 |
#파이썬 기초 14일차 (0) | 2024.07.18 |
#파이썬 기초 13일차 (0) | 2024.07.17 |