Python 은 C/S 구 조 를 바탕 으로 하 는 채 팅 방 기능 에 대한 상세 한 설명 을 실현 합 니 다.
과정 소개
1.프로필
이번 프로젝트 수업 은 간단 한 채 팅 방 프로그램 을 실현 하 는 서버 쪽 과 클 라 이언 트 입 니 다.
2.지식 포인트
서버 쪽 은
asyncore
,asynchat
와socket
이 몇 가지 모듈 과 관련 되 고 클 라 이언 트 는telnetlib
,wx
,time
와thread
이 몇 가지 모듈 을 사용 했다.3.필요 한 환경
이번 시간 에 클 라 이언 트 를 만 드 는 데 필요 한
wxPython
GUI 도구 꾸러미 입 니 다.다음 명령 으로 설치 하 십시오.
$ sudo apt-get install python-wxtools
비밀번호4.프로젝트 효과 캡 처
로그 인 창
채 팅 창
5.소스 코드 다운로드
git clone https://github.com/shiyanlou/pythonchat.git
설명:상기 코드 의 다운로드 방식 을 이해 하지 못 하거나 다운로드 후 환경 에서 코드 를 찾 지 못 하면 여 기 를 클릭 하여 볼 수 있 습 니 다.
2.프로젝트 실전(서버 쪽)
1.서버 클래스
우선 채 팅 서버 가 필요 합 니 다.asyncore 의 dispatcher 류 를 계승 하여 이 루어 집 니 다.코드 는 다음 과 같 습 니 다.
class ChatServer(dispatcher):
"""
"""
def __init__(self, port):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(('', port))
self.listen(5)
self.users = {}
self.main_room = ChatRoom(self)
def handle_accept(self):
conn, addr = self.accept()
ChatSession(self, conn)
2.세 션 클래스서버 클래스 가 있 으 면 모든 사용자 의 연결 세 션 을 유지 할 수 있어 야 합 니 다.asynchat 의 async 를 계승 합 니 다.chat 클래스 에서 이 루어 집 니 다.코드 는 다음 과 같 습 니 다.
class ChatSession(async_chat):
"""
"""
def __init__(self, server, sock):
async_chat.__init__(self, sock)
self.server = server
self.set_terminator('
')
self.data = []
self.name = None
self.enter(LoginRoom(server))
def enter(self, room):
' , '
try:
cur = self.room
except AttributeError:
pass
else:
cur.remove(self)
self.room = room
room.add(self)
def collect_incoming_data(self, data):
' '
self.data.append(data)
def found_terminator(self):
' '
line = ''.join(self.data)
self.data = []
try:
self.room.handle(self, line)
except EndSession:
self.handle_close()
def handle_close(self):
async_chat.handle_close(self)
self.enter(LogoutRoom(self.server))
3.명령 해석 기로그 인,온라인 사용자 조회,메시지 보 내기 등 사용자 의 명령 을 설명 할 수 있 는 명령 해석 기 가 필요 합 니 다.코드 는 다음 과 같 습 니 다.
class CommandHandler:
"""
"""
def unknown(self, session, cmd):
' '
session.push('Unknown command: %s
' % cmd)
def handle(self, session, line):
' '
if not line.strip():
return
parts = line.split(' ', 1)
cmd = parts[0]
try:
line = parts[1].strip()
except IndexError:
line = ''
meth = getattr(self, 'do_' + cmd, None)
try:
meth(session, line)
except TypeError:
self.unknown(session, cmd)
4.방그 다음 에 채 팅 방 을 실현 해 야 합 니 다.여기 서 우 리 는 세 가지 방 을 정 의 했 습 니 다.그것 이 바로 사용자 가 막 로그 인 했 을 때의 방,채 팅 방 과 로그 인 한 방 을 탈퇴 하 는 것 입 니 다.이 세 가지 방 은 모두 공공 부모 류 가 있 습 니 다.코드 는 다음 과 같 습 니 다.
class Room(CommandHandler):
"""
,
"""
def __init__(self, server):
self.server = server
self.sessions = []
def add(self, session):
' '
self.sessions.append(session)
def remove(self, session):
' '
self.sessions.remove(session)
def broadcast(self, line):
' '
for session in self.sessions:
session.push(line)
def do_logout(self, session, line):
' '
raise EndSession
class LoginRoom(Room):
"""
"""
def add(self, session):
' '
Room.add(self, session)
session.push('Connect Success')
def do_login(self, session, line):
' '
name = line.strip()
if not name:
session.push('UserName Empty')
elif name in self.server.users:
session.push('UserName Exist')
else:
session.name = name
session.enter(self.server.main_room)
class ChatRoom(Room):
"""
"""
def add(self, session):
' '
session.push('Login Success')
self.broadcast(session.name + ' has entered the room.
')
self.server.users[session.name] = session
Room.add(self, session)
def remove(self, session):
' '
Room.remove(self, session)
self.broadcast(session.name + ' has left the room.
')
def do_say(self, session, line):
' '
self.broadcast(session.name + ': ' + line + '
')
def do_look(self, session, line):
' '
session.push('Online Users:
')
for other in self.sessions:
session.push(other.name + '
')
class LogoutRoom(Room):
"""
"""
def add(self, session):
' '
try:
del self.server.users[session.name]
except KeyError:
pass
5.서버 쪽 전체 코드
#!/usr/bin/python
# encoding: utf-8
from asyncore import dispatcher
from asynchat import async_chat
import socket, asyncore
PORT = 6666 #
class EndSession(Exception):
"""
"""
pass
class CommandHandler:
"""
"""
def unknown(self, session, cmd):
' '
session.push('Unknown command: %s
' % cmd)
def handle(self, session, line):
' '
if not line.strip():
return
parts = line.split(' ', 1)
cmd = parts[0]
try:
line = parts[1].strip()
except IndexError:
line = ''
meth = getattr(self, 'do_' + cmd, None)
try:
meth(session, line)
except TypeError:
self.unknown(session, cmd)
class Room(CommandHandler):
"""
,
"""
def __init__(self, server):
self.server = server
self.sessions = []
def add(self, session):
' '
self.sessions.append(session)
def remove(self, session):
' '
self.sessions.remove(session)
def broadcast(self, line):
' '
for session in self.sessions:
session.push(line)
def do_logout(self, session, line):
' '
raise EndSession
class LoginRoom(Room):
"""
"""
def add(self, session):
' '
Room.add(self, session)
session.push('Connect Success')
def do_login(self, session, line):
' '
name = line.strip()
if not name:
session.push('UserName Empty')
elif name in self.server.users:
session.push('UserName Exist')
else:
session.name = name
session.enter(self.server.main_room)
class ChatRoom(Room):
"""
"""
def add(self, session):
' '
session.push('Login Success')
self.broadcast(session.name + ' has entered the room.
')
self.server.users[session.name] = session
Room.add(self, session)
def remove(self, session):
' '
Room.remove(self, session)
self.broadcast(session.name + ' has left the room.
')
def do_say(self, session, line):
' '
self.broadcast(session.name + ': ' + line + '
')
def do_look(self, session, line):
' '
session.push('Online Users:
')
for other in self.sessions:
session.push(other.name + '
')
class LogoutRoom(Room):
"""
"""
def add(self, session):
' '
try:
del self.server.users[session.name]
except KeyError:
pass
class ChatSession(async_chat):
"""
"""
def __init__(self, server, sock):
async_chat.__init__(self, sock)
self.server = server
self.set_terminator('
')
self.data = []
self.name = None
self.enter(LoginRoom(server))
def enter(self, room):
' , '
try:
cur = self.room
except AttributeError:
pass
else:
cur.remove(self)
self.room = room
room.add(self)
def collect_incoming_data(self, data):
' '
self.data.append(data)
def found_terminator(self):
' '
line = ''.join(self.data)
self.data = []
try:
self.room.handle(self, line)
except EndSession:
self.handle_close()
def handle_close(self):
async_chat.handle_close(self)
self.enter(LogoutRoom(self.server))
class ChatServer(dispatcher):
"""
"""
def __init__(self, port):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(('', port))
self.listen(5)
self.users = {}
self.main_room = ChatRoom(self)
def handle_accept(self):
conn, addr = self.accept()
ChatSession(self, conn)
if __name__ == '__main__':
s = ChatServer(PORT)
try:
asyncore.loop()
except KeyboardInterrupt:
print
3.프로젝트 실전(클 라 이언 트)서버 쪽 을 완성 하면 클 라 이언 트 를 실현 해 야 합 니 다.여기 클 라 이언 트 연결 서버 는
telnetlib
모듈 을 사 용 했 습 니 다.1.로그 인 창
여기 있 는 그래 픽 인터페이스 팩 은
wxPython
을 선 택 했 습 니 다.앞 에 설치 설명 이 있 습 니 다.로그 인 창 은 계승wx.Frame
류 를 통 해 이 루어 집 니 다.코드 는 다음 과 같 습 니 다.
class LoginFrame(wx.Frame):
"""
"""
def __init__(self, parent, id, title, size):
' , '
wx.Frame.__init__(self, parent, id, title)
self.SetSize(size)
self.Center()
self.serverAddressLabel = wx.StaticText(self, label = "Server Address", pos = (10, 50), size = (120, 25))
self.userNameLabel = wx.StaticText(self, label = "UserName", pos = (40, 100), size = (120, 25))
self.serverAddress = wx.TextCtrl(self, pos = (120, 47), size = (150, 25))
self.userName = wx.TextCtrl(self, pos = (120, 97), size = (150, 25))
self.loginButton = wx.Button(self, label = 'Login', pos = (80, 145), size = (130, 30))
self.loginButton.Bind(wx.EVT_BUTTON, self.login)
self.Show()
def login(self, event):
' '
try:
serverAddress = self.serverAddress.GetLineText(0).split(':')
con.open(serverAddress[0], port = int(serverAddress[1]), timeout = 10)
response = con.read_some()
if response != 'Connect Success':
self.showDialog('Error', 'Connect Fail!', (95, 20))
return
con.write('login ' + str(self.userName.GetLineText(0)) + '
')
response = con.read_some()
if response == 'UserName Empty':
self.showDialog('Error', 'UserName Empty!', (135, 20))
elif response == 'UserName Exist':
self.showDialog('Error', 'UserName Exist!', (135, 20))
else:
self.Close()
ChatFrame(None, -2, title = 'ShiYanLou Chat Client', size = (500, 350))
except Exception:
self.showDialog('Error', 'Connect Fail!', (95, 20))
def showDialog(self, title, content, size):
' '
dialog = wx.Dialog(self, title = title, size = size)
dialog.Center()
wx.StaticText(dialog, label = content)
dialog.ShowModal()
2.채 팅 창채 팅 창 에서 가장 중요 한 것 은 서버 에 메 시 지 를 보 내 고 서버 의 메 시 지 를 받 는 것 입 니 다.여 기 는 하위 스 레 드 를 통 해 받 아들 입 니 다.코드 는 다음 과 같 습 니 다.
class ChatFrame(wx.Frame):
"""
"""
def __init__(self, parent, id, title, size):
' , '
wx.Frame.__init__(self, parent, id, title)
self.SetSize(size)
self.Center()
self.chatFrame = wx.TextCtrl(self, pos = (5, 5), size = (490, 310), style = wx.TE_MULTILINE | wx.TE_READONLY)
self.message = wx.TextCtrl(self, pos = (5, 320), size = (300, 25))
self.sendButton = wx.Button(self, label = "Send", pos = (310, 320), size = (58, 25))
self.usersButton = wx.Button(self, label = "Users", pos = (373, 320), size = (58, 25))
self.closeButton = wx.Button(self, label = "Close", pos = (436, 320), size = (58, 25))
self.sendButton.Bind(wx.EVT_BUTTON, self.send)
self.usersButton.Bind(wx.EVT_BUTTON, self.lookUsers)
self.closeButton.Bind(wx.EVT_BUTTON, self.close)
thread.start_new_thread(self.receive, ())
self.Show()
def send(self, event):
' '
message = str(self.message.GetLineText(0)).strip()
if message != '':
con.write('say ' + message + '
')
self.message.Clear()
def lookUsers(self, event):
' '
con.write('look
')
def close(self, event):
' '
con.write('logout
')
con.close()
self.Close()
def receive(self):
' '
while True:
sleep(0.6)
result = con.read_very_eager()
if result != '':
self.chatFrame.AppendText(result)
3.클 라 이언 트 전체 코드
#!/usr/bin/python
# encoding: utf-8
import wx
import telnetlib
from time import sleep
import thread
class LoginFrame(wx.Frame):
"""
"""
def __init__(self, parent, id, title, size):
' , '
wx.Frame.__init__(self, parent, id, title)
self.SetSize(size)
self.Center()
self.serverAddressLabel = wx.StaticText(self, label = "Server Address", pos = (10, 50), size = (120, 25))
self.userNameLabel = wx.StaticText(self, label = "UserName", pos = (40, 100), size = (120, 25))
self.serverAddress = wx.TextCtrl(self, pos = (120, 47), size = (150, 25))
self.userName = wx.TextCtrl(self, pos = (120, 97), size = (150, 25))
self.loginButton = wx.Button(self, label = 'Login', pos = (80, 145), size = (130, 30))
self.loginButton.Bind(wx.EVT_BUTTON, self.login)
self.Show()
def login(self, event):
' '
try:
serverAddress = self.serverAddress.GetLineText(0).split(':')
con.open(serverAddress[0], port = int(serverAddress[1]), timeout = 10)
response = con.read_some()
if response != 'Connect Success':
self.showDialog('Error', 'Connect Fail!', (95, 20))
return
con.write('login ' + str(self.userName.GetLineText(0)) + '
')
response = con.read_some()
if response == 'UserName Empty':
self.showDialog('Error', 'UserName Empty!', (135, 20))
elif response == 'UserName Exist':
self.showDialog('Error', 'UserName Exist!', (135, 20))
else:
self.Close()
ChatFrame(None, -2, title = 'ShiYanLou Chat Client', size = (500, 350))
except Exception:
self.showDialog('Error', 'Connect Fail!', (95, 20))
def showDialog(self, title, content, size):
' '
dialog = wx.Dialog(self, title = title, size = size)
dialog.Center()
wx.StaticText(dialog, label = content)
dialog.ShowModal()
class ChatFrame(wx.Frame):
"""
"""
def __init__(self, parent, id, title, size):
' , '
wx.Frame.__init__(self, parent, id, title)
self.SetSize(size)
self.Center()
self.chatFrame = wx.TextCtrl(self, pos = (5, 5), size = (490, 310), style = wx.TE_MULTILINE | wx.TE_READONLY)
self.message = wx.TextCtrl(self, pos = (5, 320), size = (300, 25))
self.sendButton = wx.Button(self, label = "Send", pos = (310, 320), size = (58, 25))
self.usersButton = wx.Button(self, label = "Users", pos = (373, 320), size = (58, 25))
self.closeButton = wx.Button(self, label = "Close", pos = (436, 320), size = (58, 25))
self.sendButton.Bind(wx.EVT_BUTTON, self.send)
self.usersButton.Bind(wx.EVT_BUTTON, self.lookUsers)
self.closeButton.Bind(wx.EVT_BUTTON, self.close)
thread.start_new_thread(self.receive, ())
self.Show()
def send(self, event):
' '
message = str(self.message.GetLineText(0)).strip()
if message != '':
con.write('say ' + message + '
')
self.message.Clear()
def lookUsers(self, event):
' '
con.write('look
')
def close(self, event):
' '
con.write('logout
')
con.close()
self.Close()
def receive(self):
' '
while True:
sleep(0.6)
result = con.read_very_eager()
if result != '':
self.chatFrame.AppendText(result)
' '
if __name__ == '__main__':
app = wx.App()
con = telnetlib.Telnet()
LoginFrame(None, -1, title = "Login", size = (280, 200))
app.MainLoop()
소결마지막 으로 프로그램 을 실행 하여 채 팅 을 할 수 있 습 니 다.서버 를 먼저 시작 하고 클 라 이언 트 를 시작 해 야 합 니 다.이 항목 은 서버,asynchat 의 asyn 을 구현 하기 위해 asyncore dispatcher 를 사용 합 니 다.chat 는 사용자 의 연결 세 션 을 유지 하고
wxPython
으로 그래 픽 인터페이스 를 실현 하 며telnetlib
로 서버 를 연결 하여 하위 스 레 드 에서 서버 가 보 낸 메 시 지 를 받 아들 여 간단 한 채 팅 방 프로그램 이 완성 되 었 습 니 다.더 많은 파 이 썬 관련 내용 은 본 사이트 의 주 제 를 볼 수 있 습 니 다.
본 논문 에서 말 한 것 이 여러분 의 Python 프로 그래 밍 에 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.