Python3群聊聊天室

it2025-01-29  11

类似群聊

需求

有人进入聊天室需要输入姓名,姓名不能重复有人进入聊天室时,其他人会收到通知:xxx 进入了聊天室一个人发消息,其他人会收到:xxx : xxxxxxxxxxx有人退出聊天室,则其他人也会收到通知:xxx退出了聊天室

技术分析

客户端/服务端

client/server

存储人员信息: 服务端 存什么 : 名字 地址 怎么存 : {name:address} [(name,address),...] class Person: def __init__(self,name,address): self.name = name self.address = address 消息的网络传递 : udp 消息发送:转发的方法 客户端-》服务端-》客户端 收发消息: 多进程,一个负责发送,一个负责接收
功能模块划分 封装方法 : 函数封装
框架模型 进入聊天室 聊天 退出聊天室
网络协议设置
请求类型 数据参量 进入 LOGIN name 聊天 CHAT name 说话的内容 退出 EXIT
功能模块逻辑具体分析
框架模型 服务端 : 1. 创建udp网络服务端 2. 循环接收各种客户端请求 3. 根据请求做出调用 客户端 : 1. 创建udp网络 进入聊天室 客户端 : 1. 输入姓名 2. 发送给服务端 3. 接收服务端反馈 4. YES 进入聊天 NO 回到第一步 服务端 : 1. 接收请求 2. 判断是否有这个姓名 3. 根据判断发送结果 YES -》存储用户 告知其他人 NO -》over 聊天 客户端 :1. 创建子进程 2. 父进程循环发送消息 子进程循环接收消息 服务端 : 1. 接收请求 2. 将消息转发给其他人 退出聊天室 客户端 1. 输入EXIT 表示退出 2. 发送请求 服务端 1. 接收请求 2. 告知其他人 3. 删除该用户 后续可继续优化完善
客户端代码如下:
# -*- coding: UTF-8 -*- ''' PyCharm @Project :群聊聊天室 @File :chat_client.py @Author : @Date :2020/10/24 ''' """ 群聊 客户端代码 """ from socket import * from multiprocessing import Process import sys # 服务器地址 ADDR = ('127.0.0.1', 8888) # 处理登录 def login(socketed): while True: # 进入聊天室 name = input('用户名:>>>') # 发送姓名 msg = 'LOGIN ' + name socketed.sendto(msg.encode(), ADDR) # 接收结果 data, address = socketed.recvfrom(1024) if data.decode() == 'YES': print('进入聊天室') return name else: print('用户已存在') # 接收消息 def chat(socketed): while True: data, address = socketed.recvfrom(1024 * 10) # 美化打印内容 msg = "\n" + data.decode() + "\n发言:" print(msg, end="") # end="" 不换行 # 发送消息 def receive(socketed, name): while True: # try 处理异常退出 try: news = input('发言:') except KeyboardInterrupt: news = 'EXIT' if news == 'EXIT': msg = 'EXIT ' + name socketed.sendto(msg.encode(), ADDR) sys.exit('已退出聊天室') msg = 'CHAT %s %s' % (name, news) socketed.sendto(msg.encode(), ADDR) # 程序启动函数 def main(): socketed = socket(AF_INET, SOCK_DGRAM) # socketed.bind(('0.0.0.0', 2222)) # 确保地址不会变化 name = login(socketed) # 进入聊天室 # 创建子进程 用于接收消息 process = Process(target=chat, args=(socketed,)) process.daemon = True # 父进程退出子进程也退出 process.start() # 父进程发送消息 receive(socketed, name) socketed.close() process.join() if __name__ == '__main__': main()
服务端代码如下:
# -*- coding: UTF-8 -*- ''' PyCharm @Project :群聊聊天室 @File :chat_server.py @Author : @Date :2020/10/24 ''' """ 群聊  服务端 """ from socket import * from multiprocessing import Process # 服务器地址 HOST='0.0.0.0' PORT= 8888 ADDR = (HOST,PORT) # 用字典储存用户 user = {} # 储存用户信息 {name:address} # 处理进入聊天室 def login(socketed, name, address): if name in user or '管理' in name: socketed.sendto('NO'.encode(), address) else: socketed.sendto('YES'.encode(), address) # 循环通知其他人 msg = '欢迎%s进入聊天室' % name for other in user: socketed.sendto(msg.encode(), user[other]) user[name] = address # 增加该用户 # 处理聊天 def chat(socketed, name,content): msg = "%s : %s" % (name, content) for other in user: if other == name: continue # 除去自己 socketed.sendto(msg.encode(), user[other]) # 处理退出 def exits(socketed, name): del user[name] # 删除用户 msg = '%s退出聊天室' % name for other in user: socketed.sendto(msg.encode(), user[other]) # 处理客户端请求 def request(socketed): # 循环接收各种客户端请求 while True: # 接收所有客户端请求 data, address = socketed.recvfrom(1024) # 对数据结构进行简单解析 tmp = data.decode().split(' ',2) if tmp[0] == 'LOGIN': # tmp---> ['LOGIN','name'] # 进入函数 login(socketed, tmp[1], address) elif tmp[0] == 'CHAT': # tmp---> ['LOGIN','name','news'] #  聊天函数 chat(socketed, tmp[1],tmp[2]) elif tmp[0] == 'EXIT': # 退出函数 exits(socketed, tmp[1]) # 程序启动函数 def main(): # UDP套接字 socketed = socket(AF_INET, SOCK_DGRAM) socketed.bind(ADDR) # 创建子进程 process=Process(target=request,args=(socketed,)) process.daemon=True # 父进程退出子进程也退出 process.start() while True: # 发送管理员消息 content = input("管理员消息:") # 服务端退出 if content == "EXIT": break msg = "CHAT 管理员消息: "+content # 从父进程发送给子进程 socketed.sendto(msg.encode(),ADDR) if __name__ == '__main__': main() 执行需先执行服务端后再执行客户端
最新回复(0)