如何运用python多线程实现UDP通信

如何运用python多线程实现UDP通信

最近在做通信与网络的课程实践,遇到了使用UDP实现socket编程,然而。。。我找不到使用多线程的代码!!!
其实有找到一个的但因为使用的是os块的pid函数,而本Windows系统表示不能使用这个函数,所以我只能自己改改改,终于写好了使用多线程实现UDP通信啦~

服务器:server.py

import socket
import threading

# 创建 UDP 套接字
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 设置端口复用

server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 绑定地址

address = ('127.0.0.1', 8888)
server.bind(address)

userlist = {}  # 此字典用于存放客户端的名字和地址

# 处理客户端请求的函数
def doRequest():
    while True:
        # 接收来自客户端的消息
        msg, addr = server.recvfrom(1024)
        msglist = msg.decode().split(' ')  # 拆分数据,以空格为分隔
        if msglist[0] == 'login':  # 如果是进入聊天室请求
            doLogin(msglist[1], addr)
           # sendAZ()
        elif msglist[0] == 'speak':
            # msglist:['c','name','content']
            content = ' '.join(msglist[2:])  # 获取完整发送内容
            # 发送给其他所有成员
            doChat(content, msglist[1])
        elif msglist[0] == 'quit':
            doQuit(msglist[1])

#发送A到Z
def sendAZ():
    for i in range(65, 91):
        message = '服务器:%s' % chr(i)
        print('发送:%s' % chr(i))
        server.sendto(message.encode(), address)


# 客户端退出处理函数
def doQuit(name):
    message = '\n%s 退出了聊天室' % name
    for u in userlist:
        if u != name:
            server.sendto(message.encode(), userlist[u])
        else:
            server.sendto('exit'.encode(), userlist[name])
        # 从存储结构中删除
    del userlist[name]


# 用于聊天的函数(把内容发送给其他成员)
def doChat(content, name):
    message = '\n%s 说:%s' % (name, content)
    for u in userlist:
        if u != name:  # 发给不是自身的所有客户端
            server.sendto(message.encode(), userlist[u])


# 列表用字典存储{name,addr}
# 进入聊天室请求处理函数
def doLogin(name, addr):
    # 判断姓名是否同名
    if (name in userlist) :  # 如果列表中已经存在此用户名
        server.sendto('该用户已经存在!'.encode(), addr)
        return  # 函数结束,返回继续接收新的数据
    # 同名不存在,发送信号给客户端,运行进入
    server.sendto('OK'.encode(), addr)
    # 通知所有人
    message = '\n欢迎%s进入聊天室' % name
    for u in userlist:
        server.sendto(message.encode(), userlist[u])  # 全发
    userlist[name] = addr  # 加入到存储结构userlist字典中
    print(userlist)
    for i in range(65, 91):
        message = '服务器:%s' % chr(i)
        print('发送:%s' % chr(i))
        server.sendto(message.encode(), userlist[name])


# 创建多线程,让子进程负责管理员喊话,父进程和客户端交互
t = threading.Thread(target=doRequest(), args=(server,))
t.start()

for client in userlist:
    client.close()
print('-'*5+'服务器断开连接'+'-'*5)

客户端:client.py

import socket
import threading

address = ('127.0.0.1', 8888)
# 创建 UDP 套接字
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 接收用户输入,包装后发送给服务器
while True:
    name = input('请输入姓名:')
    message = 'login ' + name  # 此处加入标记
    client.sendto(message.encode(), address)
    data, addr = client.recvfrom(1024)
    if data.decode() == 'OK':
        print('您已经进入聊天室...')
        break

    else:  # 不允许进入
        # 打印不允许进入的原因
        print(data.decode())


def sendmsg():
    # 发送消息给服务器,服务器群发给所有客户端
    while True:
        content = input('请发言(输入quit 退出):')
        if content == 'quit':
            message = 'quit ' + name
            client.sendto(message.encode(), address)
            print('退出')
            client.close()  # 子进程退出

        # 包装消息
        message = 'speak %s %s' % (name, content)
        client.sendto(message.encode(), address)


def recvmsg():
    while True:
        message, addr = client.recvfrom(1024)
        if message.decode() == 'exit':  # 如果收到服务器此消息,父进程退出
            # 关闭连接
            print('退出')
            client.close()
        # 因为print覆盖了之前的input界面,在这里重新输出一遍
        print(message.decode() + '\n请发言(quit退出):', end='')


send_thread = threading.Thread(target=sendmsg)
send_thread.start()

recv_thread = threading.Thread(target=recvmsg)
# 设置成为守护进程
recv_thread.setDaemon(True)
recv_thread.start()

send_thread.join()

# 关闭连接
print('-'*5+'服务器断开连接'+'-'*5)
client.close()

文中因为有老师要求的源代码自动给客户端发送A~Z,所以中间的一部分是当有新的客户端连上服务器后,服务器将自动发送A-Z给这个客户端。

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值