类似群聊
需求
- 有人进入聊天室需要输入姓名,姓名不能重复
- 有人进入聊天室时,其他人会收到通知: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. 删除该用户
客户端代码如下:
'''
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="")
def receive(socketed, name):
while True:
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)
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()
服务端代码如下:
'''
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 = {}
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':
login(socketed, tmp[1], address)
elif tmp[0] == 'CHAT':
chat(socketed, tmp[1],tmp[2])
elif tmp[0] == 'EXIT':
exits(socketed, tmp[1])
def main():
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()