类似群聊
需求
有人进入聊天室需要输入姓名,姓名不能重复有人进入聊天室时,其他人会收到通知: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
()
执行需先执行服务端后再执行客户端