【问题标题】:Python and C++ Sockets converting packet dataPython 和 C++ 套接字转换数据包数据
【发布时间】:2010-04-14 13:06:54
【问题描述】:

首先,明确我的目标:我们实验室有两个用 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 格式、操作它们并将它们转发给接收器的最简单方法是什么?

【问题讨论】:

    标签: c++ python networking sockets binary


    【解决方案1】:

    您可以在正确连接的 socked 上通过 .recv 调用接收数据包的 50 字节(如果 TCP 数据包被分段,则实际上可能需要多次调用,因此请检查传入长度,直到您正好有 50 字节在手中;-)。

    之后,理解 C 代码令人费解。 ints(大概每个 4 字节)到 Packet[9]Packet[13] 等的分配给人的印象是打算在 Packet 内一次设置 4 个字节,但事实并非如此:每个分配在数据包中设置一个字节,从int 的最低字节开始,这是分配的 RHS。但那些字节是(int)(720000+armcontrolpacket-&gt;dof0_rot*1000) 的字节等等......

    那么数据包的最后 44 个字节必须被解释为 11 个 4 字节整数(有符号?无符号?)还是 44 个独立值?我猜是前者,然后……:

    import struct
    f = '>x4bx11i'
    values = struct.unpack(f, packet)
    

    f 格式表示:big-endian,4 个无符号字节值,被两个忽略的“备用”字节包围,11 个 4 字节有符号整数。元组 values 最终有 15 个值:四个单字节(在您的示例中为 50、1、2、1),然后是 11 个有符号整数。您可以使用相同的格式字符串将修改后的元组版本打包回一个 50 字节的数据包以重新发送。

    由于您在数据包中明确放置了长度,因此不同的数据包可能具有不同的长度(尽管这与您的 C 示例中的固定长度声明不兼容)在这种情况下,您需要更准确地接收和打开包装;但是这些细节取决于你没有提供的信息,所以我将停止猜测;-)。

    【讨论】:

    • 酷.. thx 正是我正在寻找的。让我们看看它是否有效......我将在这里报告我的成功。
    • 我有一个问题:如果我使用 gnu 程序“netcat”将输入从我的 python 脚本重定向到标准输入,然后在标准输入上使用 struct-module,这种方法是否有效?
    • @yeus,对不起,我对 netcat 的了解还不够,无法保证这会起作用——尽管如果它只是逐字节复制,应该没什么区别。
    【解决方案2】:

    看看struct module,特别是打包和解包功能。它们使用格式字符串,允许您指定要写入或读取的类型以及要使用的字节序和对齐方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-28
      • 2019-06-13
      • 2015-11-26
      • 2012-10-07
      • 1970-01-01
      相关资源
      最近更新 更多