基于UDP的跨网特定设备通信及Socket共享方案咨询
网关UDP通信问题咨询
核心疑问
- 仅知晓目标设备所在网络的公网IP和设备MAC地址,能否在未创建Socket的情况下,通过UDP向跨网的特定设备发送数据?
现有方案与困惑
- 当前方案:接收UDP数据后,将设备信息(MAC、本地IP地址、网关地址等)以JSON格式存入Redis,该场景无需持久化,Redis可满足需求。
- 困惑点:向特定客户端发送数据时,考虑将接收数据后的Socket存入字典(例如借助Twisted模块实现),但不确定是否可以跨模块共享该Socket字典,还是将所有任务放在同一模块更合适?另外已知Socket对象序列化存入Redis再反序列化后会失效。
补充:已实现部分与当前代码问题
已完成客户端数据解析并存入Redis,且测试代码(如下)可正常向设备发送UDP数据(设备能触发继电器),但通过FastAPI接口处理请求后发送UDP数据时遇到问题,相关代码如下:
FastAPI服务代码
import asyncio import uvicorn from fastapi import FastAPI from pydantic import BaseModel import socket import utils from Server import Server from ServerCommands import ServerCommands as sc #------------------------- eventHandler = Server() async def send_udp_message_async(udp_socket, add , message: bytes): try: bytes_sent = udp_socket.sendto(message, add) print("MENSAJE ENVIADO ASYNC") return bytes_sent except Exception as e: print("Error al enviar el mensaje UDP:", str(e)) finally: udp_socket.close() async def receive_response(udp_socket, desired_response, timeout): loop = asyncio.get_event_loop() print("ingresa receive response") # 1. 定义数据类型 class Msg(BaseModel): msg: str mac: str add: tuple[str, int] = [] id: int # 2. 定义API对象 app = FastAPI() @app.on_event("startup") async def startup_event(): global UDP_HOST, UDP_PORT UDP_HOST = "0.0.0.0" UDP_PORT = 5002 @app.post("/send-udp/") async def send_udp_message(inp: Msg): try: udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_socket.setblocking(False) cmd_send = eventHandler.comandos.Ingreso() print(f"cmd_send: {cmd_send.hex()}") socket_device = await utils.check_placa(inp.mac, inp.add, inp.id) print(f"socket_device: {socket_device}, {type(socket_device)}") bytes_sent = await send_udp_message_async(udp_socket, socket_device, cmd_send) print("Tarea asincrona para enviar UDP iniciada") return {"message": f"Tarea asincrona de envío UDP iniciada a {socket_device}", "response": bytes_sent} except Exception as e: return {"error": str(e)} # if __name__=="__main__": uvicorn.run('main_prueba:app', host='0.0.0.0', port=8000, reload=True)
可正常发送的测试代码
import socket from ServerCommands import ServerCommands as sc SC = sc() # 客户端数据 cliente_ip = '181.45.185.233' # 替换为客户端公网IP cliente_puerto = 5002 # 替换为客户端端口 # 创建UDP Socket udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) puerto_local = 5002 # 服务器本地端口 udp_socket.bind(('0.0.0.0', puerto_local)) mensaje = SC.Ingreso() try: # 向客户端发送消息 udp_socket.sendto(mensaje, (cliente_ip, cliente_puerto)) print('Mensaje enviado exitosamente al cliente.') except Exception as e: print(f'Error al enviar el mensaje: {str(e)}') finally: udp_socket.close()
内容的提问来源于stack exchange,提问作者agustinlezcano
相关产品推荐
相关产品推荐

