Python练习2-基本聊天程序-虚拟茶会话
基本聊天程序
先來(lái)個(gè)基本的測(cè)試?yán)?#xff1a;
Main.py
from asyncore import dispatcher import socket,asyncore PORT = 11223 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)def handle_accept(self):conn,addr = self.accept()print ('Connection attempt from',addr[0])if __name__ == '__main__':s = ChatServer(PORT)try:asyncore.loop() except KeyboardInterrupt:pass? ??上面是服務(wù)器段程序,接受到連接之后馬上在服務(wù)器上顯示對(duì)方IP,但是不保持連接。客戶端測(cè)試的話很簡(jiǎn)單,可以自己寫一個(gè)socket的連接,也可以為了省事直接本地開啟telnet就行了,開啟telnet的方法是,在開始菜單里搜索:
然后確定,之后cmd里直接telnet就行了。
運(yùn)行上面的main.py,然后客戶端鏈接服務(wù)端:
Cmd->telnet????:?open?127.0.0.1?11223
? ? 上面就是一個(gè)最基本的Python服務(wù)器腳本流程。接下來(lái)實(shí)現(xiàn)一個(gè)基本的聊天程序用來(lái)練手。
? ? ?實(shí)現(xiàn)的基本功能(虛擬茶會(huì)話)?測(cè)試環(huán)境python?3.6.0[python基礎(chǔ)教程上的代碼不能直接在3.6.0版本上跑,以下是改過(guò)的虛擬茶會(huì)話]
功能:
login?name?登錄房間
logout?退出房間
say???XXXX?發(fā)言
look?查看同一個(gè)房間內(nèi)的人
who?查看誰(shuí)登陸了當(dāng)前服務(wù)器
測(cè)試截圖
?
簡(jiǎn)單說(shuō)下設(shè)計(jì)結(jié)構(gòu):
CommandHandler類?:?處理命令的,函數(shù)存在則執(zhí)行,不存在則直接走unknown函數(shù)。結(jié)合著try和getattr函數(shù)python可以直接嘗試去執(zhí)行一個(gè)不確定存不存在的函數(shù)。[我一直在想,別的語(yǔ)言要怎么實(shí)現(xiàn)這個(gè)東西,是創(chuàng)建虛擬工廠?對(duì)了想起來(lái)了,干脆就創(chuàng)建一些函數(shù),然后把函數(shù)名字格式化封裝在一個(gè)void指針容器里的了。函數(shù)格式化要統(tǒng)一]
Room類:表示一個(gè)房間,里面有一些對(duì)房間人[鏈接]數(shù)據(jù)結(jié)構(gòu)的增加刪除操作,同時(shí)還有相關(guān)廣播函數(shù),用于把消息發(fā)給所有人。
LoginRoom類,里面有成功登陸房間,登陸房間失敗以及登陸操作,比如問(wèn)候登陸者,同時(shí)通知?jiǎng)e人有人登陸等細(xì)節(jié)。
LogoutRoom類,登出房間類,用戶登出房間時(shí)候進(jìn)行的一些數(shù)據(jù)結(jié)構(gòu)處理。
ChatRoom類,聊天室類,主要就是封裝了一些功能函數(shù)。比如say?look?who等等。
ChatSession,ChatServer?類基本的服務(wù)器程序需要的,分別繼承async_chat和dispatcher,處理一些服務(wù)器參數(shù),以及重載設(shè)置一些處理函數(shù)等。
?
詳細(xì)代碼如下[注意本代碼測(cè)試于python3.6.0]
#!/usr/bin/env python3 __author__ = 'tcstory' from asyncore import dispatcher from asynchat import async_chat import socket, asyncorePORT=5005 NAME='TestChat'class EndSession(Exception): passclass CommandHandler:'''Simple command handler similar to cmd.Cmd from the standard library'''def unknown(self, session, cmd):'Respond to an unknown command'session.push('Unkonw command: {0}\r\n'.format(cmd).encode())def handle(self, session, line):'Handle a received line from a given session'if not line.strip():return#Split off the commandparts = line.split(' ', 1)cmd = parts[0]try:line=parts[1].strip()except IndexError:line=''#Try to find a handlermeth=getattr(self,'do_'+cmd,None)try:#Assume it's callablemeth(session,line)except TypeError:#If it isn't ,respond to the unknown commandself.unknown(session,cmd)class Room(CommandHandler):'''A generic environment that may contain one or more users(sessions).it takes care of basic command handling and broadcasting.'''def __init__(self,server):self.server=serverself.sessions=[]def add(self,session):'A session(user) has entered the room'self.sessions.append(session)def remove(self,session):'A session (user) has left the room'self.sessions.remove(session)def broadcast(self,line):'Send a line to all sessions in the room'for session in self.sessions:session.push(line.encode())def do_logout(self,session,line):'Respond to the logout command'raise EndSessionclass LoginRoom(Room):'''A room meant for a single person who has just connected'''def add(self,session):Room.add(self,session)#When a user enters,greet him/herself.broadcast('Welcome to {0}\r\n'.format(self.server.name))def unknown(self, session, cmd):#All unknown commands (anything except login or logout)#results in a proddingsession.push('Please log in\nUse "login <nick>"\r\n'.encode())def do_login(self,session,line):name=line.strip()#Make sure the user has entered a nameif not name:session.push('Please enter a name\r\n'.encode())#Make sure that the name isn't in useelif name in self.server.users:session.push('The name {0} is taken.\r\n'.format(name).encode())session.push('Please try again.\r\n'.encode())else:#The name is OK,os it is stored in the session.and#the user is moved into the main roomsession.name=namesession.enter(self.server.main_room)class ChatRoom(Room):'''A room meant for multiple users who can chat with the others in the room'''def add(self,session):#Notify everyone that a new user has enteredself.broadcast('{0} has entered the room.\r\n'.format(session.name))self.server.users[session.name]=sessionRoom.add(self,session)def remove(self,session):Room.remove(self,session)#Notify everyone that a user has leftself.broadcast('{0} has left the room.\r\n'.format(session.name))def do_say(self,session,line):self.broadcast(('{0}: '+line+'\r\n').format(session.name))def do_look(self,session,line):'Handles the look command,used to see who is in a room'session.push('The following are in this room:\r\n'.encode())for other in self.sessions:session.push('{0}\r\n'.format(other.name).encode())def do_who(self,session,line):'Handles the who command ,used to see who is logged in'session.push('The following are logged in:\r\n'.encode())for name in self.server.users:session.push('{0}\r\n'.format(name).encode())class LogoutRoom(Room):'''A simple room for a single user.Its sole purpose is to remove the user's name from the server'''def add(self,session):#When a session (user) enters the LogoutRoom it is deletedtry:del self.server.users[session.name]except KeyError:passclass ChatSession(async_chat):'''A single session,which takes care of the communication with a single user'''def __init__(self,server,sock):# async_chat.__init__(self,sock)super().__init__(sock)self.server=serverself.set_terminator(b'\r\n')self.data=[]self.name=None#All sessions begin in a separate LoginRoomself.enter(LoginRoom(server))def enter(self,room):# Remove self from current room and add self to next room....try:cur=self.roomexcept AttributeError:passelse:cur.remove(self)self.room=roomroom.add(self)def collect_incoming_data(self, data):self.data.append(data.decode('utf-8'))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):'''A chat server with a single room'''def __init__(self,port,name):super().__init__()# dispatcher.__init__(self)self.create_socket(socket.AF_INET,socket.SOCK_STREAM)self.set_reuse_addr()self.bind(('',port))self.listen(5)self.name=nameself.users={}self.main_room=ChatRoom(self)def handle_accept(self):conn,addr=self.accept()ChatSession(self,conn)if __name__=='__main__':s=ChatServer(PORT,NAME)try:asyncore.loop()except KeyboardInterrupt:print()總結(jié)
以上是生活随笔為你收集整理的Python练习2-基本聊天程序-虚拟茶会话的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python练习1-文档格式化成html
- 下一篇: Python练习3-XML-RPC实现简