写在前面的絮絮叨叨

运行环境:需安装python3.x和对应python3.x的wxpython库

windows操作系统:pip install wx
Linux操作系统:也可通过pip下载wxpython,进入https://extras.wxpython.org/wxPython4/extras/linux/gtk3/选择相对应操作系统的wxpython.whl进行下载
踩过的坑:假如安装wxpython之后运行代码还是报错:No model named “wx”,就检查一下所安装的wxpython是否是支持python3.x的

项目代码

不带注释总代码行在200行左右,已上传至github:https://github.com/atuo-200/chat_room

server.py

import asynchat
import asyncore
import time# 定义端口
PORT = 6666# 定义结束异常类
class EndSession(Exception):passclass ChatServer(asyncore.dispatcher):"""创建一个支持多用户连接的聊天服务器"""#重写构造方法def __init__(self, port):#显式调用父类构造方法asyncore.dispatcher.__init__(self)# 创建socketself.create_socket()# 设置 socket 为可重用self.set_reuse_addr()# 监听端口self.bind(('', port))#设置最大连接数为5,超出排队self.listen(5)self.users = {}self.main_room = ChatRoom(self)def handle_accept(self):#阻塞式监听,等待客户端的连接,生成连接对象(SSL通道,客户端地址)conn, addr = self.accept()#建立会话ChatSession(self, conn)class ChatSession(asynchat.async_chat):"""负责和客户端通信的会话类"""def __init__(self, server, sock):asynchat.async_chat.__init__(self, sock)self.server = server#设置数据终止符self.set_terminator(b'\n')#设置数据列表self.data = []self.name = Noneself.enter(LoginRoom(server))def enter(self, 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.encode("utf-8"))# 退出聊天室的处理except EndSession:self.handle_close()def handle_close(self):# 当 session 关闭时,将进入 LogoutRoomasynchat.async_chat.handle_close(self)self.enter(LogoutRoom(self.server))class CommandHandler:"""命令处理类"""#定义未知命令的处理方法def unknown(self, session, cmd):# 通过 aynchat.async_chat.push 方法发送消息,向客户端发送错误提示session.push(('不知名命令 {} \n'.format(cmd)).encode("utf-8"))def handle(self, session, line):#解码line = line.decode()#判断去掉空格后是否还有数据if not line.strip():return#把数据以空格分隔符分割生成列表,最大分割数为1parts = line.split(' ', 1)#分割的第一部分为命令cmd = parts[0]#将分割后的第二部分去除空格保存到变量try:line = parts[1].strip()except IndexError:line = ''#获取指定名称的方法对象method = getattr(self, 'do_' + cmd, None)#调用获取到的方法对象try:method(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):#遍历所有用户会话,再使用 asynchat.asyn_chat.push 方法发送数据for session in self.sessions:session.push(line)def do_logout(self, session, line):# 退出房间raise EndSessionclass LoginRoom(Room):"""处理登录用户"""def add(self, session):# 用户连接成功的回应Room.add(self, session)# 使用 asynchat.asyn_chat.push 方法发送数据到客户端session.push('连接成功'.encode('utf-8'))def do_login(self, session, line):# 用户登录逻辑name = line.strip()# 获取用户名称if not name:session.push('用户名为空'.encode('utf-8'))# 检查是否有同名用户elif name in self.server.users:session.push('用户名已存在'.encode('utf-8'))# 用户名检查成功后,进入主聊天室else:session.name = namesession.enter(self.server.main_room)class LogoutRoom(Room):"""处理退出用户"""def add(self, session):# 从服务器中用户字典中移除相关记录try:del self.server.users[session.name]except KeyError:passclass ChatRoom(Room):"""聊天用的房间"""def add(self, session):# 广播新用户进入session.push('登录成功'.encode('utf-8'))self.broadcast((session.name + ' 进入房间\n').encode("utf-8"))#向服务器的用户字典添加与会话的用户名相对应的会话self.server.users[session.name] = sessionRoom.add(self, session)def remove(self, session):# 广播用户离开Room.remove(self, session)self.broadcast((session.name + ' 离开房间\n').encode("utf-8"))def do_say(self, session, line):# 客户端发送消息print(line)self.broadcast(('time:'+time.strftime('%H:%M:%S',time.localtime(time.time()))+ '\n'+session.name + ': ' + line + '\n').encode("utf-8"))def do_look(self, session, line):# 查看在线用户session.push('在线用户:\n'.encode('utf-8'))for other in self.sessions:session.push((other.name + '\n').encode("utf-8"))if __name__ == '__main__':s = ChatServer(PORT)try:print("chat serve run at '127.0.0.1:{0}'".format(PORT))#开启循环监听网络事件asyncore.loop()except KeyboardInterrupt:print("chat server exit")

client.py

import wx
import telnetlib
from time import sleep
import _thread as threadclass LoginFrame(wx.Frame):"""登录窗口类,继承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="服务器地址", pos=(10, 50), size=(120, 25))#用户名框标签           self.userNameLabel = wx.StaticText(self, label="用户名", 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='登录', 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 != '连接成功'.encode('utf-8'):self.showDialog('Error', '连接失败!', (200, 100))returncon.write(('login ' + str(self.userName.GetLineText(0)) + '\n').encode("utf-8"))response = con.read_some()if response == '用户名为空'.encode('utf-8'):self.showDialog('Error', '用户名为空!', (200, 100))elif response == '用户名已存在':self.showDialog('Error', '用户名已存在!', (200, 100))else:self.Close()ChatFrame(None, 2, title='阿坨聊天室', size=(500, 400))except Exception:self.showDialog('Error', '连接失败!', (195, 120))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):"""聊天窗口类,继承wx.Frame类"""def __init__(self, parent, id, title, size):# 初始化,添加控件wx.Frame.__init__(self, parent, id, title)self.SetSize(size)self.Center()#显示对话文本框,style设置其文本高亮显示和只读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)# Users按钮绑定获取在线用户数量方法self.usersButton.Bind(wx.EVT_BUTTON, self.lookUsers)# 关闭按钮绑定关闭方法self.closeButton.Bind(wx.EVT_BUTTON, self.close)#调用thread模块中的start_new_thread()来产生新线程负责接收服务器信息#第一个参数为线程要执行函数的函数名,第二个参数为需要传递给函数的实参,为tuple,若该函数不需要参数也要传入空tuple       thread.start_new_thread(self.receive, ())self.Show()def send(self, event):# 发送消息message = str(self.message.GetLineText(0)).strip()if message != '':#这里的'say '不可随意变动,为呼应server.py中命令处理类定义的handle(),实现文字聊天协议而存在con.write(('say ' + message + '\n').encode("utf-8"))self.message.Clear()def lookUsers(self, event):#查看当前在线用户con.write(b'look\n')def close(self, event):# 关闭窗口con.write(b'logout\n')con.close()self.Close()def receive(self):# 接受服务器的消息while True:sleep(0.6)#在I/O中读取数据,存在result变量中result = con.read_very_eager()if result != '':self.chatFrame.AppendText(result)if __name__ == '__main__':#应用程序对象app = wx.App()#客户端使用telnetlib连接目标主机con = telnetlib.Telnet()#顶级窗口对象LoginFrame(None, -1, title="Login", size=(320, 250))#进入应用程序的主事件循环app.MainLoop()

项目来源

python实现文字聊天室 | 实验楼

所使用的第三方库

使用asyncore和asynchat实现异步通信编程
使用wxpython实现GUI界面编程

聊天服务器将同多个 socket 进行通信,所以我们可以基于 asyncore 模块实现聊天服务器。asyncore 模块是一个异步的 socket 处理器,通过使用该模块将大大简化异步编程的难度。asynchat 模块在 asyncore 模块的基础上做了进一步封装,简化了基于文本协议的通信任务的开发难度

区分同步通信和异步通信

同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

参考资料

项目思路:python实现文字聊天室 | 实验楼
了解python网络编程:python3网络编程 | 菜鸟教程
关于socket的类型:简单理解socket(AF_INET&SOCK_STREAM,SOCK_DGRAM)
asyncore开发文档:asyncore | python中文开发手册

运行效果

用python实现多人聊天室小项目笔记相关推荐

  1. 基于Python的多人聊天室的设计与实现

    基于Python的多人聊天室的设计与实现 摘要  本文介绍了基于即时通讯的Python实现web版多人聊天室的设计和实现.这个系统利用了多种先进的技术,如Django.Channels.WebSock ...

  2. 基于python面向对象多人聊天室

    基于python面向对象多人聊天室 1.项目环境 项目名称:多人聊天室 项目模式:C/S 开发环境:win10+python3.8+pycharm 所需知识:python GUI编程,多线程编程,网络 ...

  3. vc udp 广播接收和发送_udp聊天?使用udp+python实现多人聊天室

    信来到这个文章里面的朋友不会对udp陌生,话不多说直接开始. 由于udp没有建立连接,也没有实际上的客户端和服务器端. 但是我们需要让一个udp来充当服务器!实现消息广播从而达到聊天室的效果. 以下是 ...

  4. Netty - 一个简单的聊天室小项目

     经过一段时间对Netty的学习,我们对Netty各版本以及像ProtocolBuffers等技术应用都有了不少相关的了解, 我们就用这段时间学到的只是做一个简单的聊天室的小项目来练习自己学到的技术. ...

  5. C语言实现QQ聊天室小项目 [完整源码]

    聊天小项目用于练习Windows下的 tcp socket编程和线程同步,其中send 和 recv 使用,对tcp数据传输时经常遇到的中文乱码.数据残缺等问题有示范和纠正作用. 项目效果图 客户端代 ...

  6. python socket 多人聊天室

    参考来源(其实我从上面复制了一点): Python 的 Socket 编程教程  http://www.oschina.net/question/12_76126 Python线程指南 http:// ...

  7. Python简单多人聊天室

    # ------------------------------服务器端-----------------------------------------# auther: kele # 创建时间:2 ...

  8. python实现简易聊天需要登录博客园zip下载_Python基于Socket实现简易多人聊天室的示例代码...

    前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的 ...

  9. python聊天室_python实现简单多人聊天室

    本文实例为大家分享了python实现多人聊天室的具体代码,供大家参考,具体内容如下 刚开始学习python,写了一个聊天室练练手. Server.py import socket,select,thr ...

  10. python多人聊天室_python实现简单多人聊天室

    本文实例为大家分享了python实现多人聊天室的具体代码,供大家参考,具体内容如下 刚开始学习python,写了一个聊天室练练手. Server.py import socket,select,thr ...

最新文章

  1. Spring OXM-XStream快速入门
  2. 石板切割问题c语言_天长井盖切割机切圆机市政窨井盖切圆机
  3. 《系统集成项目管理》第十五章 信息(文档)和配置管理
  4. javascript:面向对象编程基础:继承
  5. 算法练习day20——190411(重建二叉树、斐波那契数列、跳台阶、矩形覆盖、变态跳台阶、旋转数组的最小数字、矩阵中的路径)
  6. Java项目性能监控和调优工具-Javamelody
  7. Exchange 2013 创建发送连接器
  8. 42Exchange 2010升级到Exchange 2013-证书申请配置
  9. 浏览器开发者工具,自己设置屏幕分辨率调试(chrome)
  10. Linux - Vim常用命令清单
  11. android刷机教程 华为,华为手机刷机教程(华为手机强制刷机步骤图文教程)
  12. 关于kali的pycharm创建快捷方式
  13. 第六周博客作业西北师范大学|李晓婷
  14. ideal在编译的时候报程序包不存在错误
  15. 微服务资源库太强了,学习手册限时开源
  16. Android实现snmp协议(一)
  17. html5 幽灵按钮,弥散阴影幽灵按钮
  18. 今年世界杯预测(阿根廷队冠军)
  19. https详解,ssl详解,学不会来打死我
  20. 欢迎随时回家——python制作一个火车票抢票版本(附完整代码,仅供学习参考)

热门文章

  1. 荣事达Royalstar无叶暖风机——功能逻辑与能耗分析
  2. 计算机linux认证-1,Linux认证:Linux点评Debian5个五功能
  3. 利用Mono-cecil实现.NET程序的重新签名,重新链接相关库的引用
  4. 东京大学招生海报上的那些事(上)
  5. 从ChargePoint到能链智电,充电服务商的价值创新
  6. VB打造QQ批量登陆器
  7. 【华为云技术分享】让电变“机灵”,华为云与开发者共同打造智慧用电
  8. 物联网竞赛-LoRa和NB-IOT模块学习知识汇总
  9. win10系统如何删除不用的输入法
  10. 阿里云短信服务接口触发天级流控Permits:10