多任务编程
群聊聊天室
- 有人进入聊天室需要输入姓名,姓名不能重复
- 有人进入聊天室时,其他人会收到通知:Lucy 进入了聊天室
- 一个人发消息,其他人会收到: Lucy : 一起出去玩啊。
- 有人退出聊天室,则其他人也会收到通知 : Lucy 退出了聊天室
- 扩展功能:服务器可以向所有用户发送公告: 管理员消息: 大家好,欢迎进入聊天室。
服务端参考代码
from socket import *
from multiprocessing import Process
# 服务器地址
HOST = "0.0.0.0"
PORT = 8888
ADDR = (HOST, PORT)
# 存储用户信息 {name:address}
user = {}
# 处理进入聊天室
def login(sock, name, address):
if name in user or "管理" in name:
sock.sendto(b"FAIL", address)
else:
sock.sendto(b"OK", address)
# 告知其他人
msg = "欢迎 %s 进入聊天室" % name
for key, value in user.items():
sock.sendto(msg.encode(), value)
user[name] = address # 存储用户
# print(user) # 测试
# 处理聊天
def chat(sock, name, content):
msg = "%s : %s" % (name, content)
for key, value in user.items():
# 不是本人就发送
if key != name:
sock.sendto(msg.encode(), value)
# 处理退出
def exit(sock, name):
if name in user:
del user[name] # 删除该用户
# 通知其他用户
msg = "%s 退出聊天室" % name
for key, value in user.items():
sock.sendto(msg.encode(), value)
def handle(sock):
# 不断接收请求,分情况讨论
while True:
request, addr = sock.recvfrom(1024)
tmp = request.decode().split(" ", 2)
# 分情况讨论
if tmp[0] == "LOGIN":
# tmp ->[LOGIN,name]
login(sock, tmp[1], addr)
elif tmp[0] == "CHAT":
# tmp ->[CHAT,name,content]
chat(sock, tmp[1], tmp[2])
elif tmp[0] == "EXIT":
# tmp ->[EXIT,name]
exit(sock, tmp[1])
# 程序入口函数
def main():
# 创建udp
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(ADDR)
# 接收请求,分类处理
p = Process(target=handle, args=(sock,), daemon=True)
p.start()
while True:
content = input("管理员消息:")
if not content:
break
msg = "CHAT 管理员消息 " + content
# 从父进程发送到子进程
sock.sendto(msg.encode(), ADDR)
if __name__ == '__main__':
main()
客户端参考代码
from socket import *
from multiprocessing import Process
import sys
# 服务器地址
SERVER_ADDR = ("124.71.188.218", 8888)
def login(sock):
while True:
name = input("请输入昵称:")
# 组织请求
msg = "LOGIN " + name
sock.sendto(msg.encode(), SERVER_ADDR)
result, addr = sock.recvfrom(1024)
if result == b"OK":
print("进入聊天室")
return name
else:
print("该昵称已存在")
# 子进程接收函数
def recv_msg(sock):
while True:
data, addr = sock.recvfrom(1024 * 10)
# 格式处理
content = "\n" + data.decode() + "\n发言:"
print(content, end="")
# 父进程发送函数
def send_msg(sock, name):
while True:
try:
content = input("发言:")
except KeyboardInterrupt:
content = "exit"
# 表示退出
if content == 'exit':
msg = "EXIT " + name
sock.sendto(msg.encode(), SERVER_ADDR)
sys.exit("您已退出聊天室")
msg = "CHAT %s %s" % (name, content)
sock.sendto(msg.encode(), SERVER_ADDR)
def main():
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(("0.0.0.0",55224)) # 端口不要变
name = login(sock) # 请求进入聊天室
# 子进程负责接收
p = Process(target=recv_msg, args=(sock,), daemon=True)
p.start()
send_msg(sock, name) # 发送消息
if __name__ == '__main__':
main()
最后一次更新于2022-11-29 15:37
0 条评论