聊天功能分析
1.网络搭建
2.进入聊天室
客户端:
1.输入姓名
2.将请求发送给服务器
3.接收结果,允许进入则可以聊天,不允许则重新输入姓名
服务器:
1.接收请求
2.判断姓名是否存在,如果允许进入,存储用户基本信息,通知其他客户端,如不允许则结束
3.将结果通知客户端
3.聊天
客户端
1.创建新的进程
2.一个进程循环接收消息
3.一个进程循环接收消息
服务器
1.接收请求
2.判断请求类型
3.将消息转发给其他人
4.退出聊天
客户端
输入quit或者ctrl+c退出
将请求发送服务器
结束进程
服务器
接收请求
将退出消息告知其他人
给该用户发送EXIT
删除用户
5.管理员消息
6.通信协议设置
进入聊天室:L
聊天:C
退出:Q
服务器反馈:OK表示成功,其它表示失败
客户端收到 EXIT 退出接收进程
聊天代码
聊天服务器端代码
"""
聊天室
env: python3.10
socket udp & fork
"""
from socket import *
import os, sys
"""
全局变量:被多个模块使用或有一定固定含义
"""
ADDR = ('0.0.0.0', 8888)
user = {}
def do_login(s, name, addr):
if name in user or "管理员" in name:
s.sendto("该用户存在".encode(), addr)
return
s.sendto(b'OK', addr)
msg = "\n欢迎'%s'进入聊天室" % name
for i in user:
s.sendto(msg.encode(), user[i])
user[name] = addr
def do_chat(s, name, text):
msg = "\n%s : %s " %(name, text)
for i in user:
if i != name:
s.sendto(msg.encode(), user[i])
def do_quit(s, name):
msg = "\n%s 退出聊天室" %name
for i in user:
if i!= name:
s.sendto(msg.encode(), user[i])
else:
s.sendto(b'EXIT', user[i])
del user[name]
def do_request(s):
while True:
data, addr = s.recvfrom(1024)
tmp = data.decode().split(' ')
if tmp[0] == 'L':
do_login(s, tmp[1], addr)
elif tmp[0] == 'C':
text = ' '.join(tmp[2:])
do_chat(s, tmp[1], text)
elif tmp[0] == "Q":
do_quit(s, tmp[1])
print(data.decode())
def main():
s = socket(AF_INET, SOCK_DGRAM)
s.bind(ADDR)
pid = os.fork()
if pid == 0:
while True:
msg = input("管理员消息:")
msg = "C 管理员 " + msg
s.sendto(msg.encode(), ADDR)
else:
do_request(s)
main()
聊天客户端代码
"""
聊天室 客户端
发送请求,展示结果
"""
from socket import *
import os, sys
ADDR = ('127.0.0.1', 8888)
def send_msg(s, name):
while True:
try:
text = input("发言:")
except KeyboardInterrupt:
text = 'quit'
if text.strip() == "quit":
msg = "Q " + name
s.sendto(msg.encode(), ADDR)
sys.exit("退出聊天室")
msg = "C %s %s" %(name, text)
s.sendto(msg.encode(), ADDR)
def recv_msg(s):
while True:
try:
data, addr = s.recvfrom(4096)
except KeyboardInterrupt:
sys.exit()
if data.decode() == "EXIT":
sys.exit()
print(data.decode())
def main():
s = socket(AF_INET, SOCK_DGRAM)
while True:
name = input("请输入姓名:")
msg = 'L ' + name
s.sendto(msg.encode(), ADDR)
data, addr = s.recvfrom(128)
if data.decode() == "OK":
print("您已进入聊天室")
else:
print(data.decode()+"\n发言:", end='')
pid = os.fork()
if pid < 0:
sys.exit("Error!")
elif pid == 0:
send_msg(s, name)
else:
recv_msg(s)
main()