Python群聊-UDP实现

方法:
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()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值