方法:
1.UDP协议
2.多线程
服务端:
import socket
import threading
'''
主线程实现管理员功能,分支线程实现添加用户与信息的转发
'''
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(("0.0.0.0",8888))
# 储存进入群聊的用户名
user = {}
# 分支线程执行函数
def forward(user):
while True:
data,addr = sock.recvfrom(5120)
en_data = data.decode("utf-8")
# 处理客户端进入请求
if en_data[0] == "*":
ls_data = en_data.split(" ")
if ls_data[1] in user:
sock.sendto("00".encode(), addr) # 表示重名
continue
sock.sendto("成功进入群聊".encode("utf-8"),addr)
for u in user:
sock.sendto(("%s进入群聊" % ls_data[1]).encode("utf-8"), user[u])
print("\n%s进入群聊\n请管理员输入信息:" % ls_data[1], end="")
user[ls_data[1]] = addr
# 处理客户端退出请求
elif en_data[0] == "#":
ls_data = en_data.split(" ")
for u in user:
if u == ls_data[1]:
continue
sock.sendto(("%s退出群聊" % ls_data[1]).encode("utf-8"), user[u])
print("\n%s退出群聊\n请管理员输入信息:" % ls_data[1], end="")
del user[ls_data[1]]
# 转发信息
else:
for u in user:
if user[u] == addr:
continue
sock.sendto(data, user[u])
# 创建分支线程
thread1 = threading.Thread(name="分支线程1",target=forward,args=(user,),kwargs={})
thread1.daemon = True #设置分支线程随主线程的退出而退出
thread1.start()
while True:
data = input("请管理员输入信息:")
if data == "#":
# 退出服务端
break
send_data = "管理员说:%s" % data
for u in user:
sock.sendto(send_data.encode("utf-8"),user[u])
sock.close()
客户端:
import socket
import threading
'''
主进程负责发送信息,分支进程负责接收信息
使用状态变量控制控制台的使用权
'''
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
addr = ("127.0.0.1",8888)
# 储存对话信息
recv_data = []
# 储存程序状态,若为空字符串为输入状态,此时只会接收服务端信息,而不会在控制台打印
state = "0"
# 请求进入群聊
while True:
name = input("请输入用户名:")
if "#" in name:
print("用户名中不能包含#号")
continue
if "管理员" in name:
print("用户名中不能包含‘管理员’")
continue
sock.sendto(("* %s" % name).encode("utf-8"),addr)
ser_data,ser_addr = sock.recvfrom(1024)
if ser_data.decode("utf-8") == "00":
print("用户名重复")
continue
print(ser_data.decode("utf-8"))
break
# 分支线程执行函数
def client_recv():
global state
while True:
ser_data,ser_addr = sock.recvfrom(5120)
if state == "":
recv_data.append(ser_data.decode("utf-8"))
continue
print(ser_data.decode("utf-8"))
# 创建分支线程
thread = threading.Thread(name="分支线程",target=client_recv,args=(),kwargs={})
thread.daemon = True #设置分支线程随主线程的退出而退出
thread.start()
# 向服务端发送信息
while True:
# 按回车进入输入状态
state = input()
data = input("我说:")
if data == "":
for re in recv_data:
print(re)
recv_data.clear()
state = "0"
continue
if data[0] == "*":
print("请勿以*号开头")
for re in recv_data:
print(re)
recv_data.clear()
state = "0"
continue
# 输入#号退出
if data[0] == "#":
con = input("以#号开头表示退出群聊,输入1确认退出,输入0重新输入:")
if con == "0":
for re in recv_data:
print(re)
recv_data.clear()
state = "0"
continue
sock.sendto(("# %s" % name).encode("utf-8"), addr)
print("已退出群聊")
break
sock.sendto(("%s说:%s" % (name, data)).encode("utf-8"), addr)
for re in recv_data:
print(re)
recv_data.clear()
state = "0"
sock.close()