Python 和 C++套接字转换数据包
首先明确一下我的目标:我们实验室有两个用C编写的程序。我正在为他们开发一个代理服务器(双向)(这也将负责数据)。我想用 Python 编写代理服务器。重要的是要知道我对这两个程序几乎一无所知,我只知道数据包的定义文件。
现在:假设 C++ 程序之一中的数据包定义如下所示:
unsigned char Packet[0x32]; // Packet[Length]
int z=0;
Packet[0]=0x00; // Spare
Packet[1]=0x32; // Length
Packet[2]=0x01; // Source
Packet[3]=0x02; // Destination
Packet[4]=0x01; // ID
Packet[5]=0x00; // Spare
for(z=0;z<=24;z+=8)
{
Packet[9-z/8]=((int)(720000+armcontrolpacket->dof0_rot*1000)/(int)pow((double)2,(double)z));
Packet[13-z/8]=((int)(720000+armcontrolpacket->dof0_speed*1000)/(int)pow((double)2,(double)z));
Packet[17-z/8]=((int)(720000+armcontrolpacket->dof1_rot*1000)/(int)pow((double)2,(double)z));
Packet[21-z/8]=((int)(720000+armcontrolpacket->dof1_speed*1000)/(int)pow((double)2,(double)z));
Packet[25-z/8]=((int)(720000+armcontrolpacket->dof2_rot*1000)/(int)pow((double)2,(double)z));
Packet[29-z/8]=((int)(720000+armcontrolpacket->dof2_speed*1000)/(int)pow((double)2,(double)z));
Packet[33-z/8]=((int)(720000+armcontrolpacket->dof3_rot*1000)/(int)pow((double)2,(double)z));
Packet[37-z/8]=((int)(720000+armcontrolpacket->dof3_speed*1000)/(int)pow((double)2,(double)z));
Packet[41-z/8]=((int)(720000+armcontrolpacket->dof4_rot*1000)/(int)pow((double)2,(double)z));
Packet[45-z/8]=((int)(720000+armcontrolpacket->dof4_speed*1000)/(int)pow((double)2,(double)z));
Packet[49-z/8]=((int)armcontrolpacket->timestamp/(int)pow(2.0,(double)z));
}
if(SendPacket(sock,(char*)&Packet,sizeof(Packet)))
return 1;
return 0;
接收该数据、将其转换为可读的 python 格式、操作它们并将它们转发到接收器的最简单方法是什么?
First of all, to clarify my goal: There exist two programs written in C in our laboratory. I am working on a Proxy Server (bidirectional) for them (which will also mainpulate the data). And I want to write that proxy server in Python. It is important to know that I know close to nothing about these two programs, I only know the definition file of the packets.
Now: assuming a packet definition in one of the C++ programs reads like this:
unsigned char Packet[0x32]; // Packet[Length]
int z=0;
Packet[0]=0x00; // Spare
Packet[1]=0x32; // Length
Packet[2]=0x01; // Source
Packet[3]=0x02; // Destination
Packet[4]=0x01; // ID
Packet[5]=0x00; // Spare
for(z=0;z<=24;z+=8)
{
Packet[9-z/8]=((int)(720000+armcontrolpacket->dof0_rot*1000)/(int)pow((double)2,(double)z));
Packet[13-z/8]=((int)(720000+armcontrolpacket->dof0_speed*1000)/(int)pow((double)2,(double)z));
Packet[17-z/8]=((int)(720000+armcontrolpacket->dof1_rot*1000)/(int)pow((double)2,(double)z));
Packet[21-z/8]=((int)(720000+armcontrolpacket->dof1_speed*1000)/(int)pow((double)2,(double)z));
Packet[25-z/8]=((int)(720000+armcontrolpacket->dof2_rot*1000)/(int)pow((double)2,(double)z));
Packet[29-z/8]=((int)(720000+armcontrolpacket->dof2_speed*1000)/(int)pow((double)2,(double)z));
Packet[33-z/8]=((int)(720000+armcontrolpacket->dof3_rot*1000)/(int)pow((double)2,(double)z));
Packet[37-z/8]=((int)(720000+armcontrolpacket->dof3_speed*1000)/(int)pow((double)2,(double)z));
Packet[41-z/8]=((int)(720000+armcontrolpacket->dof4_rot*1000)/(int)pow((double)2,(double)z));
Packet[45-z/8]=((int)(720000+armcontrolpacket->dof4_speed*1000)/(int)pow((double)2,(double)z));
Packet[49-z/8]=((int)armcontrolpacket->timestamp/(int)pow(2.0,(double)z));
}
if(SendPacket(sock,(char*)&Packet,sizeof(Packet)))
return 1;
return 0;
What would be the easiest way to receive that data, convert it into a readable python format, manipulate them and send them forward to the receiver?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以在正确连接的 socked 上通过
.recv
调用接收数据包的 50 字节(万一 TCP 数据包被分段,实际上可能需要多次调用,因此请检查传入长度,直到您获得手中正好有 50 个字节;-)。之后,对C代码的理解就令人费解了。将
int
(大概每个 4 个字节)分配给Packet[9]
、Packet[13]
等,给人的印象是目的是在Packet
中一次设置 4 个字节,但事实并非如此:每次分配都从int
的最低字节开始在数据包中设置一个字节。这是作业的 RHS。但这些字节是(int)(720000+armcontrolpacket->dof0_rot*1000)
的字节等等......所以数据包的最后 44 个字节必须解释为 11 4 字节整数(有符号?无符号?)还是 44 个独立值?我猜是前者,并且做...:
格式
f
表示:big-endian,4 个无符号字节值,周围有两个被忽略的“备用”字节,11 个 4 字节有符号整数。元组values
最终有 15 个值:四个单字节(在示例中为 50、1、2、1),然后是 11 个有符号整数。您可以使用相同的格式字符串将元组的修改版本打包回 50 字节的数据包中以重新发送。由于您明确地将长度放入数据包中,因此不同的数据包可能具有不同的长度(尽管这与 C 示例中的固定长度声明不兼容),在这种情况下,您需要在接收和解包时更加准确;然而,这些细节取决于您不提供的信息,所以我将停止尝试猜测;-)。
You can receive the packet's 50 bytes with a
.recv
call on a properly connected socked (it might actually take more than one call in the unlikely event the TCP packet gets fragmented, so check incoming length until you have exactly 50 bytes in hand;-).After that, understanding that C code is puzzling. The assignments of
int
s (presumably 4-bytes each) toPacket[9]
,Packet[13]
, etc, give the impression that the intention is to set 4 bytes at a time withinPacket
, but that's not what happens: each assignment sets exactly one byte in the packet, from the lowest byte of theint
that's the RHS of the assignment. But those bytes are the bytes of(int)(720000+armcontrolpacket->dof0_rot*1000)
and so on...So must those last 44 bytes of the packet be interpreted as 11 4-byte integers (signed? unsigned?) or 44 independent values? I'll guess the former, and do...:
the format
f
indicates: big-endian, 4 unsigned-byte values surrounded by two ignored "spare" bytes, 11 4-byte signed integers. Tuplevalues
ends up with 15 values: the four single bytes (50, 1, 2, 1 in your example), then 11 signed integers. You can use the same format string to pack a modified version of the tuple back into a 50-bytes packet to resend.Since you explicitly place the length in the packet it may be that different packets have different lenghts (though that's incompatible with the fixed-length declaration in your C sample) in which case you need to be a bit more accurate in receiving and unpacking it; however such details depend on information you don't give, so I'll stop trying to guess;-).
看一下 struct 模块,特别是 pack 和 unpack 函数。它们使用格式字符串,允许您指定要写入或读取的类型以及要使用的字节序和对齐方式。
Take a look at the struct module, specifically the pack and unpack functions. They work with format strings that allow you to specify what types you want to write or read and what endianness and alignment you want to use.