导航

python实现发送udp数据包数据

Posted on 2023-08-19 16:25  rossxp  阅读(484)  评论(0编辑  收藏  举报

需求:python发送udp数据包数据,支持host、port、valueFile等启动参数,其中valueFile是json格式的文件,要解析编码完成转换。

分模块实现:

发送端:

导入所需的模块和类,例如sys、logging、argparse、json、socket以及datetime和timedelta。

定义一个Sender类,变量MULTI_TABLE_HEADER和SINGLE_TABLE_HEADER分别表示多表模式和单表模式下的消息头;变量interval表示发送消息的时间间隔,默认为5秒;变量is_multi_table表示是否使用多表模式,默认为True;变量udp_host和udp_port分别表示UDP服务器的主机和端口,默认为'localhost'和12345;变量value_file表示JSON值文件的路径,默认为'value.json'。

    MULTI_TABLE_HEADER = "80000000"
    SINGLE_TABLE_HEADER = "80000001"

    interval = 5
    is_multi_table = True
    udp_host = 'localhost'
    udp_port = 12345
    value_file = 'resources/value.json'

方法send_message_to_udp_server用于将消息发送到UDP服务器,使用socketAPI。

    def send_message_to_udp_server(self,host, port, message):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # message = b'Hello, UDP!'
        sock.sendto(message, (host, port))
        sock.close()

方法run是主要的运行逻辑。它读取指定的JSON文件,并构造一个DqMessage对象。然后循环发送消息到UDP服务器,发送完成后等待一定时间再次发送,直到程序停止运行,同时保存日志信息。

    def run(self):

        # 读取valueFile指定的JSON文件
        with open(self.value_file) as file:
            dq_params = json.load(file)

        # 构造DqMessage对象
        dq_message = DqMessage()
        dq_message.header = self.MULTI_TABLE_HEADER if self.is_multi_table else self.SINGLE_TABLE_HEADER
        dq_message.dataList = [
            DqParam(dq_param['tableCode'], dq_param['seq'], dq_param['type'], dq_param['value'])
            for dq_param in dq_params
        ]
        print(dq_message.dataList)

        # 设置日志输出格式和保存路径
        logging.basicConfig(filename='send_msg.log', format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)

        while True:
            # 获取当前时间
            start_time = datetime.now()

            # 构造并发送数据包
            message = dq_message.to_byte_buf(self.is_multi_table)
            self.send_message_to_udp_server(self.udp_host, self.udp_port, message)

            # 输出日志信息
            logging.info(f"发送内容16进制:{message}")
            logging.info(f"UDP消息已发送至 {self.udp_host}:{self.udp_port}")

            # 计算下一次发送的时间点
            end_time = datetime.now()
            elapsed_time = (end_time - start_time).total_seconds()
            sleep_time = max(self.interval - elapsed_time, 0)
            sleep_time = min(sleep_time, self.interval)
            next_send_time = end_time + timedelta(seconds=sleep_time)

            # 输出日志信息
            logging.info(f"下一次发送时间:{next_send_time.strftime('%Y-%m-%d %H:%M:%S')}")

            # 等待到下一次发送的时间点
            while datetime.now() < next_send_time:
                pass

数据封装模块:Dqmessage和Dqparam是实现编码转换和数据封装的模块,不与展示,根据数据具体实现。

接收端验证主要部分:

    def receive_udp_message(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind((self.host, self.port))
     while True:
            data, addr = sock.recvfrom(1024)  # 接收数据包和发送方地址
            print('Received message:', data)
            # 输出日志信息
            logging.info(f"接收消息:{data}")
            hex_str = binascii.hexlify(data).decode('utf-8')
            print('verified message:', hex_str)
            logging.info(f"验证消息:{hex_str}")