基本聊天程序

先来个基本的测试例子:

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等等。

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

详细代码如下[注意本代码测试于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-基本聊天程序-虚拟茶会话相关推荐

  1. python写机器人程序_用Python写的一个多线程机器人聊天程序

    本人是从事php开发的, 近来想通过php实现即时通讯(兼容windows).后来发现实现起来特别麻烦, 就想到python.听说这家伙在什么地方都能发挥作用.所以想用python来做通讯模块...所 ...

  2. python聊天软件实现_python实现点对点聊天程序

    用Python实现点对点的聊天,2个程序,一个是client.py,一个是server.py,通过本机地址127.0.0.1连接进行通信,利用多线程把发送消息和接收消息分开独立进行. client代码 ...

  3. 基于TCP协议网上聊天程序(python)带界面

    基于TCP协议网上聊天程序(python)带界面 1 设计目标 基于TCP协议网上聊天程序 实现一简单的聊天程序实现网上聊天,包括服务器和客户端. (1)支持多人聊天: (2)客户端具有图形化用户界面 ...

  4. python socket编程 实现简单p2p聊天程序

    转载自:https://www.cnblogs.com/wuxie1989/p/7204887.html python socket编程 实现简单p2p聊天程序 目标是写一个python的p2p聊天的 ...

  5. 使用python和tornado实现多人网页聊天程序--界面

    标题使用python和tornado实现多人网页聊天程序 上一个文章给出了后端python的全部代码,那现在就到所有的页面处理了. 上面提到的几个页面分别有: 1.登录页面 2.注册页面 3.聊天室首 ...

  6. python的wxpyton库开发的聊天程序

    使用前请下载以下库 pip install wxpython 下载使用前wxpython前请查看相应python版本是否支持 最好是python3.6版本 ip绑定的是本机ip,有多ip者也可以绑定其 ...

  7. 基于Python+Django框架的多人在线聊天程序

    基于Python的多人在线聊天程序 项目简介 本项目的选题为项目六:聊天程序,具体项目任务如下所示: 经过开发,本项目最终实现了项目任务 2. 的大体功能,实现了多用户之间的在线聊天室. 项目分析 本 ...

  8. python TCP实现聊天程序

    这是我Python课的课程设计,按理说这种聊天程序应该用UDP的,但是我的课程设计题目是TCP的,所以就用TCP写了 由于是课程设计,所以写的也没有那么复杂,后面有时间了再添加新功能,如果有什么建议可 ...

  9. 计算机网络课程设计--基于TCP协议网上聊天程序--python实现带图形界面--socket--多线程

                                              基于TCP协议网上聊天程序 引言 21世纪是一个以网络为核心的信息时代,要实现信息化,就必须依靠完善的网络.而随着计 ...

最新文章

  1. python 线性回归_用Python实现线性回归算法
  2. Teaching Machines to Converse--阅读笔记1 摘要及介绍
  3. WCF+Silverlight一个简单的RSS阅读器(二)
  4. yunfile php,【转载】Typecho又拍云文件管理插件UpyunFile升级
  5. excel求期望_商务数据分析考试:决策树分析(Excel)-安聪
  6. 苏州中学2021届高考成绩查询,苏州中学排名前十名,2021年苏州中学排名一览表
  7. IT 拉呱室 | 论我遇到的最刺激的bug【长期福利站】
  8. ubuntu物理机上搭建Kubernetes集群 -- 准备
  9. [1] 图像预处理----图像灰度化处理
  10. 北京理工大学计算机学院放假时间,北理珠这个老师厉害了,竟然利用假期干了这么件事…...
  11. PHP微信网页授权登录
  12. 【渝粤题库】陕西师范大学165102管理心理学 作业(高起专)
  13. 九校联考-绵阳东辰国际NOIP模拟总结
  14. 华为网络设备SSH方式登录配置
  15. How to design an FPGA from scratch-1_FPGA_8_24
  16. 天猫HTMl静态页面
  17. React model
  18. 管理计算机硬件设备并使用应用软件,计算机硬件管理的基本原则
  19. 宝元系统服务器不亮,我的服务器总是自动重启?
  20. 中式红木装修——一个会呼吸的家

热门文章

  1. Realm数据库存储 使用详解
  2. [译]15个关于Chrome的开发必备小技巧
  3. 二线城市的我,和北京的同学比成长
  4. 阿里云RDS的mysql数据库占用空间超过90%的处理
  5. 恢复SQL Server被误删除的数据(再扩展)
  6. cocos2d-x 帧动画学习
  7. 后盾网lavarel视频项目---3、lavarel中子控制器继承父控制器以判断是否登录
  8. P1642 规划 01分数规划+树形DP
  9. .NETFramework-Web.Mvc:ActionResult
  10. golang使用reflects调用方法时,方法名需要首字母大写