使用 python 套接字通过 UDP 发送 ihex(intel Hex)文件
sending a ihex (intel Hex) file over UDP using python Sockets
我正在使用 IPv6 和 UDP 套接字 使用 python-2.7。我特别关注 IPv6 多播 ff02::1
,其中每个 Link-本地地址设备(具有 fe80::
)响应来自中央服务器实体的查询。
我在这些设备上连接了微控制器,需要 .ihex
(Intel Hex)形式的程序。文件片段如下:
:103100005542200135D0085A8245381131400031EE
:103110003F4002000F9308249242381120012F8370
:103120009F4F1E390011F8233F4036000F930724AC
我认为解决方法是使用 struct
并使用 pack
和 unpack
等函数,但我不确定是否发送这样的 ihex 几个 Kbs 大小的文件就可以解决这个问题。
我可以这样做吗:
#!/usr/bin/env python
from struct import pack, unpack
import socket
. # Create a UDP socket and Bind it..
.
myHexCode = open("Filename.ihex")
dataToSend = struct.pack('Paramaters for packing', myHexCode)
.
. Send data to socket..
包装参数是什么? (我应该为 Hex 文件做 !
或大端或小端 >
或 <
吗?)
备注
我不能使用 scp
或 sftp
因为这两个协议都在 TCP 上工作并且不支持多播而且我正在工作在网络损耗可能更高的环境中(无线介质)
我还应该按照此 query 的建议将 Intel Hex 文件转换为二进制文件,然后打包二进制文件吗?
使用带多播的 UDP 将文件发送给多个消费者似乎充满了问题——除非整个文件适合单个数据包。由于多种原因,UDP 数据包可能 dropped/discarded 并且您已经说过网络有损。您需要为每个消费者提供一种方法来跟踪并通知发件人有关丢失的数据包。
话虽如此,这当然是可行的。一个想法:构造一个初始数据包,您可以多次多播,中间可能有随机延迟(以确保所有站都收到它)。这个初始数据包实际上说 "About to send new program - expect N subsequent record packets").
然后发送N个数据包,可能每个发送两次。在每个数据包中放置一个识别序列号,让消费者跟踪他们收到的数据。经过一些延迟(或当所有都已收到时),让每个消费者响应一个状态数据包,说 "I got all N packets" 或 "I didn't get records 5, 98, 144, and 3019"(或基于有损的任何合适的方案)。
然后发件人可以收集这些丢失的记录 ID 并重新发送这些 ID,直到所有消费者都对他们收到整个文件感到满意为止。
为了将它们打包到数据报中,我认为发送 "intel hex" 还是二进制并不重要。在任何一种情况下,您都希望将它们作为字节流发送。二进制会更小,因此需要更少的数据包,但在发送它们的过程中没有其他区别。出于同样的原因,字节排序 select 不会有什么不同。对于简单的字节流,根本不需要使用struct
来打包。您可以发送它们。
Note: python3 distinguishes between bytes
and str
types so you would need to open the file in "binary" mode for this to remain true with python3.
但是,如果按照上面的建议,您最终在每个数据包中发送了一个序列号,则需要以某种方式对该序列号进行格式化。您可以将数字格式化为 ascii 字符串,并且不需要 struct.pack
。或者,如果您将其格式化为二进制格式,则需要 select 一种打包格式。传统的网络数据包使用 "network byte order"(实际上与 big-endian 相同)但这只是一种约定。
如果我这样做,我可能会用以下结构构造每条记录:
- 记录类型(二进制,一个字节--区分这是一个数据包)
- 记录 ID(二进制,两个字节 -- 序列号 [或更大取决于
文件有多大])
- 记录数据长度(二进制,两个字节表示记录数据字段的长度)
- 记录数据(二进制,N字节)
然后你可以用这样的东西创建有效载荷:
payload = struct.pack("!BHH", record_type, record_id, len(record_data))
+ record_data
这里我们创建了一个包含 struct.pack
的 5 字节字符串,其中包含 "header" 字段(使用网络字节顺序打包),然后简单地附加已经是一个字节的 record_data字符串。
我正在使用 IPv6 和 UDP 套接字 使用 python-2.7。我特别关注 IPv6 多播 ff02::1
,其中每个 Link-本地地址设备(具有 fe80::
)响应来自中央服务器实体的查询。
我在这些设备上连接了微控制器,需要 .ihex
(Intel Hex)形式的程序。文件片段如下:
:103100005542200135D0085A8245381131400031EE
:103110003F4002000F9308249242381120012F8370
:103120009F4F1E390011F8233F4036000F930724AC
我认为解决方法是使用 struct
并使用 pack
和 unpack
等函数,但我不确定是否发送这样的 ihex 几个 Kbs 大小的文件就可以解决这个问题。
我可以这样做吗:
#!/usr/bin/env python
from struct import pack, unpack
import socket
. # Create a UDP socket and Bind it..
.
myHexCode = open("Filename.ihex")
dataToSend = struct.pack('Paramaters for packing', myHexCode)
.
. Send data to socket..
包装参数是什么? (我应该为 Hex 文件做 !
或大端或小端 >
或 <
吗?)
备注
我不能使用
scp
或sftp
因为这两个协议都在 TCP 上工作并且不支持多播而且我正在工作在网络损耗可能更高的环境中(无线介质)我还应该按照此 query 的建议将 Intel Hex 文件转换为二进制文件,然后打包二进制文件吗?
使用带多播的 UDP 将文件发送给多个消费者似乎充满了问题——除非整个文件适合单个数据包。由于多种原因,UDP 数据包可能 dropped/discarded 并且您已经说过网络有损。您需要为每个消费者提供一种方法来跟踪并通知发件人有关丢失的数据包。
话虽如此,这当然是可行的。一个想法:构造一个初始数据包,您可以多次多播,中间可能有随机延迟(以确保所有站都收到它)。这个初始数据包实际上说 "About to send new program - expect N subsequent record packets").
然后发送N个数据包,可能每个发送两次。在每个数据包中放置一个识别序列号,让消费者跟踪他们收到的数据。经过一些延迟(或当所有都已收到时),让每个消费者响应一个状态数据包,说 "I got all N packets" 或 "I didn't get records 5, 98, 144, and 3019"(或基于有损的任何合适的方案)。
然后发件人可以收集这些丢失的记录 ID 并重新发送这些 ID,直到所有消费者都对他们收到整个文件感到满意为止。
为了将它们打包到数据报中,我认为发送 "intel hex" 还是二进制并不重要。在任何一种情况下,您都希望将它们作为字节流发送。二进制会更小,因此需要更少的数据包,但在发送它们的过程中没有其他区别。出于同样的原因,字节排序 select 不会有什么不同。对于简单的字节流,根本不需要使用struct
来打包。您可以发送它们。
Note: python3 distinguishes between
bytes
andstr
types so you would need to open the file in "binary" mode for this to remain true with python3.
但是,如果按照上面的建议,您最终在每个数据包中发送了一个序列号,则需要以某种方式对该序列号进行格式化。您可以将数字格式化为 ascii 字符串,并且不需要 struct.pack
。或者,如果您将其格式化为二进制格式,则需要 select 一种打包格式。传统的网络数据包使用 "network byte order"(实际上与 big-endian 相同)但这只是一种约定。
如果我这样做,我可能会用以下结构构造每条记录:
- 记录类型(二进制,一个字节--区分这是一个数据包)
- 记录 ID(二进制,两个字节 -- 序列号 [或更大取决于 文件有多大])
- 记录数据长度(二进制,两个字节表示记录数据字段的长度)
- 记录数据(二进制,N字节)
然后你可以用这样的东西创建有效载荷:
payload = struct.pack("!BHH", record_type, record_id, len(record_data))
+ record_data
这里我们创建了一个包含 struct.pack
的 5 字节字符串,其中包含 "header" 字段(使用网络字节顺序打包),然后简单地附加已经是一个字节的 record_data字符串。