只有管理员喊话功能没有添加,后续会继续更新!
服务端代码
import os,sys
from socket import *
# 用户登录函数
def do_login(sk,user,name,addr):
# 判断用户是否在房间字典中
if (name in user) or name == "管理员":
data = "用户"+name+"已存在"
sk.sendto(data.encode(),addr)
return
else:
# 向客户端发送OK标志
sk.sendto('OK'.encode(),addr)
data = "用户"+name+"进入了聊天室"
# 遍历字典向所有用户
for i in user:
sk.sendto(data.encode(),user[i])
# 把用户加入字典
user[name] = addr
# 转发用户聊天信息函数
def do_sends(sk,user,data,addr):
for i in user:
if user[i] != addr:
sk.sendto(data.encode(),user[i])
# 用户退出房间
def do_exit(sk,user,data,addr):
sk.sendto("quit".encode(),addr)
del user[data]
data = "用户"+data+"退出房间"
for i in user:
sk.sendto(data.encode(),user[i])
# 管理员喊话
def do_child(sk):
print("我是子进程")
# 接受客户端请求
def do_parent(sk):
user = {}
print("我是父进程")
while True:
conn,addr = sk.recvfrom(1024)
conn = conn.decode()
connlist = [conn[0],conn[2:]]
# 判断请求类型
if connlist[0] == 'B' :
# 用户登录
do_login(sk,user,conn[2:],addr)
elif connlist[0] == '&':
# 转发用户来的消息
do_sends(sk,user,conn[2:],addr)
# 用户退出房间
elif connlist[0] == 'Q':
do_exit(sk,user,conn[2:],addr)
def main():
# server address
ADDR = ('0.0.0.0',8666)
# 创建套接字
sk = socket(AF_INET,SOCK_DGRAM)
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
sk.bind(ADDR)
# 创建新的进程-->处理管理员喊话
pid = os.fork()
if pid < 0:
sys.exit("创建进程失败")
elif pid == 0:
do_child(sk)
else:
do_parent(sk)
if __name__ == "__main__" :
main()
客户端代码
import os,sys
from socket import *
# 登录聊天室
def login(sk,ADDR):
while True:
name = input("请输入姓名进入聊天室:")
data = "B "+name
# 发送登录请求
sk.sendto(data.encode(),ADDR)
# 等待服务器回复
conn, addr = sk.recvfrom(1024)
# 判断是否登录成功
if conn.decode() == 'OK':
print("您以进入聊天室")
break
else:
# 返回不成功的原因
print(conn.decode())
return name
def do_sends(sk,name,ADDR):
while True:
data = input("发言>>")
# 退出房间
if data == "quit":
# 发送Q+姓名标志给服务器
sk.sendto(("Q "+name).encode(),ADDR)
sys.exit("退出发言")
data = "& "+name +">>:"+data
sk.sendto(data.encode(),ADDR)
def do_recvs(sk):
while True:
ret,ad = sk.recvfrom(1024)
if ret.decode() == 'quit':
sys.exit("退出成功")
print(ret.decode())
# 创建套接字,登录,登录成功则创建子进程
def main():
if len(sys.argv)<3:
print("输入错误")
return
HOST = sys.argv[1]
PORT = int(sys.argv[2])
ADDR = (HOST,PORT)
# 创建UDP套接字
sk = socket(AF_INET,SOCK_DGRAM)
#登录聊天室,返回姓名
name = login(sk,ADDR)
# 创建一个新的线程负责发送信息
pid = os.fork()
if pid < 0:
sys.exit("创建进程失败")
elif pid == 0:
# 发送信息
do_sends(sk,name,ADDR)
else:
# 接受信息
do_recvs(sk)
if __name__ == "__main__" :
main()