1.提要
写一个udp程序
想把 客户端 的接收和发送消息作为异步处理,结果只循环了一次,就卡死在接受消息过程中
server端:
import socket #网络通信 TCP,UDP import time udpsever=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) udpsever.bind(("192.168.199.172",8889)) #绑定这个端口,接收这个端口的消息,参数是元组,括号不能少 while True: data,addr=udpsever.recvfrom(1024) #1024 缓冲区。recvfrom可以得到发送方的消息和地址,recv只能得到消息 print("来自",addr,"消息",data) # senddata=(data.decode("utf-8")+str(time.time())).encode("utf-8") data = data.decode("utf-8") if data == "command": print("数据正在发送") udpsever.sendto("30\r\n".encode("utf-8"),addr) print("数据已经发送") else: print("其他数据正在发送") udpsever.sendto("ok\r\n".encode("utf-8"), addr) print("其他数据已经发送")
clien端:异步(普通的 asyncio )
import threading import socket import time import asyncio async def recv(): while True: try: print("正在接收信息") data, server = sock.recvfrom(1518) data = data.decode(encoding="utf-8") print("接受信息成功 ",data) battery_data = data.replace('\n', '').replace('\r', '') if battery_data.isdigit(): print("获取电量的值为:",battery_data) try: mqtt_publish_tello_battery(battery_data,) except Exception as error: print("电量上传失败:",error) except Exception: print("接受失败") await asyncio.sleep(0.1) async def send_message(): while True: battery = "battery?" command = "command" while True: try: sock.sendto(command.encode(encoding="utf-8"), tello_address) time.sleep(1) sock.sendto(battery.encode(encoding="utf-8"), tello_address) print("数据已经发送") await asyncio.sleep(5) except Exception as error: print("发送消息失败:", error) if __name__ == '__main__': sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) tello_ip = '192.168.199.172' tello_address = (tello_ip, 8889) loop = asyncio.get_event_loop() tasks = [ send_message(),recv() ] loop.run_until_complete(asyncio.wait(tasks))
2.结果:
server端数据:等了很长时间卡着不动
clien端:异步(普通的 asyncio )数据:等了很长时间还是卡着不动
3.总结:
在同一个时间循环中,异步是同一个线程在事件循环中来回切换调用,只有遇到 异步 await 函数等待时,才会去执行可执行的函数,
而 recv 函数不可以使用 await 所以执行到 recv 时无法去执行其他函数,只有等待
4.解决方法:
1.使用多线程,接收信息(recv)和发送信息(send_message)一个用主线程一个使用子线程可以执行
2.开启两个异步循环,(其中一个事件循环还是得一个线程去启动)