欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

Python练习2-基本聊天程序-虚拟茶会话

发布时间:2025/6/17 python 9 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Python练习2-基本聊天程序-虚拟茶会话 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

基本聊天程序

先来个基本的测试例子:

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

    上面是服务器段程序,接受到连接之后马上在服务器上显示对方IP,但是不保持连接。客户端测试的话很简单,可以自己写一个socket的连接,也可以为了省事直接本地开启telnet就行了,开启telnet的方法是,在开始菜单里搜索:



然后确定,之后cmd里直接telnet就行了。



运行上面的main.py,然后客户端链接服务端:

Cmd->telnet    : open 127.0.0.1 11223


    上面就是一个最基本的Python服务器脚本流程。接下来实现一个基本的聊天程序用来练手。

     实现的基本功能(虚拟茶会话) 测试环境python 3.6.0[python基础教程上的代码不能直接在3.6.0版本上跑,以下是改过的虚拟茶会话]

功能:

login name 登录房间

logout 退出房间

say   XXXX 发言

look 查看同一个房间内的人

who 查看谁登陆了当前服务器

测试截图


 

简单说下设计结构:

CommandHandler : 处理命令的,函数存在则执行,不存在则直接走unknown函数。结合着try和getattr函数python可以直接尝试去执行一个不确定存不存在的函数。[我一直在想,别的语言要怎么实现这个东西,是创建虚拟工厂?对了想起来了,干脆就创建一些函数,然后把函数名字格式化封装在一个void指针容器里的了。函数格式化要统一]


Room类:表示一个房间,里面有一些对房间人[链接]数据结构的增加删除操作,同时还有相关广播函数,用于把消息发给所有人。


LoginRoom类,里面有成功登陆房间,登陆房间失败以及登陆操作,比如问候登陆者,同时通知别人有人登陆等细节。


LogoutRoom类,登出房间类,用户登出房间时候进行的一些数据结构处理。


ChatRoom类,聊天室类,主要就是封装了一些功能函数。比如say look who等等。


ChatSessionChatServer 类基本的服务器程序需要的,分别继承async_chatdispatcher,处理一些服务器参数,以及重载设置一些处理函数等。

 

详细代码如下[注意本代码测试于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()

总结

以上是生活随笔为你收集整理的Python练习2-基本聊天程序-虚拟茶会话的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。