简体   繁体   English

将无符号字符数组拆分为多个无符号字符数组的数组

[英]Split unsigned char array into array of multiple unsigned char array

My application is composed of a controller which has several children.我的应用程序由一个具有多个子项的控制器组成。 The controller use pipe to communicate with is a first child, and child use pipe between us to transfer the question to the next sibling.控制器使用管道与第一个孩子进行通信,孩子在我们之间使用管道将问题转移到下一个兄弟姐妹。 When a child can process the question, it sends a frame to the controller pipe to make an acquittal.当孩子可以处理问题时,它会向控制器管道发送一个帧以进行无罪释放。

My problem is because every child could write in the controller pipe, It's possible that the controller read multiple child's frame in the same stream.我的问题是因为每个孩子都可以在控制器管道中写入,控制器可能会在同一个流中读取多个孩子的帧。

So, I want to split this stream to process the child frame individual.所以,我想拆分这个流来处理子帧个体。

The controller receives only one type of frame :控制器只接收一种类型的帧:

Acquittal Frame
0                 1                 2                 3
 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       CMD       |     NODE ID     |    ERROR FLAG   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      DATA LENGTH (optional)       |                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                 |
|   DATA WITH UNDETERMINED SIZE (char *) (optional)   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    END FRAME    |
+-+-+-+-+-+-+-+-+-+

This frame is compose of multiple information :该框架由多个信息组成:

  • CMD : the acquittal commend that say to controller which question the child respond CMD : 对问题孩子回应的负责人说的无罪表扬
  • NODE ID : the unique identifier of a child NODE ID : 孩子的唯一标识符
  • Error flag : that can have different value in function of result and commands错误标志:在结果和命令的函数中可以有不同的值

The commands :命令:

  • A_SET(0xA2) : A_SET(0xA2) :
    • This command admits only 2 error flag SUCCESS(0x20) and INTERNAL_ERROR(0x50)该命令只承认 2 个错误标志 SUCCESS(0x20) 和 INTERNAL_ERROR(0x50)
    • With this cmd the frame size is 4 no data length and data使用此 cmd,帧大小为 4 无数据长度和数据
  • A_DUMP(0xD2) : A_DUMP(0xD2) :
    • This command admits only 2 error flag SUCCESS(0x20) and INTERNAL_ERROR(0x50)该命令只承认 2 个错误标志 SUCCESS(0x20) 和 INTERNAL_ERROR(0x50)
    • With this cmd the frame size is 4 no data length and data使用此 cmd,帧大小为 4 无数据长度和数据
  • A_LOOKUP(0xB2) : A_LOOKUP(0xB2) :
    • If this command has error flag INTERNAL_ERROR(0x50) or NOT_FOUND(0x44) the frame size will be 4如果此命令具有错误标志 INTERNAL_ERROR(0x50) 或 NOT_FOUND(0x44),则帧大小将为 4
    • If this command has error flag SUCCESS(0x20) the frame size will be 4 + DATA LENGTH witch is encode in two bytes如果此命令具有错误标志 SUCCESS(0x20),则帧大小将为 4 + DATA LENGTH,以两个字节进行编码

So in my case for example I want this :所以在我的例子中,我想要这个:

{0xd2,0x04,0x20,0x04,0xd2,0x05,0x20,0x04,0xd2,0x06,0x20,0x04,0xd2,0x07,0x20,0x04,0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}

And I want to extract an array that look like that :我想提取一个看起来像这样的数组:

[0] : {0xd2,0x04,0x20,0x04}
[1] : {0xd2,0x05,0x20,0x04}
[2] : {0xd2,0x06,0x20,0x04}
[3] : {0xd2,0x07,0x20,0x04}
[4] : {0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}

I have tried multiple thing to do that : with manual array parkour, with strtok() function.我尝试了多种方法来做到这一点:使用手动阵列跑酷,使用 strtok() 函数。 So, I show you the last attempt with the stork function here:所以,我在这里向您展示了 stork 函数的最后一次尝试:

enum frameComponents {
    END_FRAME=(unsigned char)0x04,
    ...
}
...

unsigned int getNbFrames(unsigned char * framesStream){
    unsigned int lenFrames = strlen((char * )framesStream);
    unsigned int i,k;
    for(i=0,k=0;i<lenFrames;i++){
        if(framesStream[i]==END_FRAME){
            k++;
        }
    }
    return k;
}


unsigned char ** deserialisation(unsigned char * frameStream){
    //this function return the number of identify frame in the stream
    unsigned int nbFrame = getNbFrames(frameStream);
    unsigned int lenFrames = strlen((char * )frameStream);
    unsigned char **framesArray = malloc(nbFrame * sizeof(unsigned char *));
    unsigned char *tempFrameStream = malloc(sizeof(unsigned char)*lenFrames+1);
    unsigned char * extractedFrame = (unsigned char *) strtok(tempFrameStream, (char *)END_FRAME);
    strcpy((char *)tempFrameStream,(char *) frameStream);
    int i = 0;
    while(extractedFrame != NULL ) {
        extractedFrame = (unsigned char *) strtok(NULL, (char *)END_FRAME);
        framesArray[i]= malloc(strlen((char *)extractedFrame)+1);
        strcpy((char *)framesArray[i],(char *)extractedFrame);
        i++;
    }
    free(tempFrameStream);
    free(extractedFrame);
    return framesArray;
}

But I have multiple problem here但我在这里有多个问题

First, strtok() don't seem to work properly because when I try with one string, I have null return in my array.首先, strtok() 似乎无法正常工作,因为当我尝试使用一个字符串时,我的数组中返回空值。 I don't know if that come from the unsigned int type of my array?我不知道这是否来自我数组的 unsigned int 类型?

Secondly, when I try to access to frame array outside the function, I have segmentation fault.其次,当我尝试访问函数外的帧数组时,出现分段错误。 Even with the malloc() in my array即使在我的数组中使用 malloc()

As your input data isn't a string but a raw byte stream (aka a stream of unsigned chars), you can't use string functions for the decoder.由于您的输入数据不是字符串而是原始字节流(又名无符号字符流),因此您不能对解码器使用字符串函数。

You need to implement a parser that takes the protocol into account, ie you need to look at each frame and see what command it is.您需要实现一个将协议考虑在内的解析器,即您需要查看每个帧并查看它是什么命令。 Once you know the command, you can parse the data accordingly.一旦你知道命令,你就可以相应地解析数据。

I will not implement a full parser for you but below is some code that show the principal.我不会为你实现一个完整的解析器,但下面是一些显示主体的代码。 The code doesn't put the frames into allocated memory (I'll leave that to you), the code just prints the frame (in 2 out of 3 cases, the last I will leave to you to implement.代码不会将帧放入分配的内存中(我将把它留给你),代码只是打印帧(在 3 种情况下的 2 种情况下,最后一个我会留给你实现。

#define A_SET (0xA2)
#define A_DUMP (0xD2)
#define A_LOOKUP (0xB2)

void deserialisation(unsigned char * frameStream, size_t n)
{
    size_t index = 0;
    while (index < n)
    {
        switch(frameStream[index])
        {
            case A_SET:
                if (index + 4 > n)
                {
                    puts("Too little data! can't continue...");
                    index = n;
                }
                else
                {
                    // Good frame - just print it for now
                    printf("A_SET cmd: ");
                    for (size_t i = 0; i < 4; ++i) printf("0x%02X ", frameStream[index + i]);
                    puts("");
                    index += 4;
                }
                break;
                
            case A_DUMP:
                if (index + 4 > n)
                {
                    puts("Too little data! can't continue...");
                    index = n;
                }
                else
                {
                    // Good frame - just print it for now
                    printf("A_DUMP cmd: ");
                    for (size_t i = 0; i < 4; ++i) printf("0x%02X ", frameStream[index + i]);
                    puts("");
                    index += 4;
                }
                break;
                
            case A_LOOKUP:
                printf("A_LOOKUP cmd: ");
                // Add code here...
                break;
                
            default:
                puts("Unknow frame! Can't continue...");
                index = n;
                break;
        }
    }
}
    
int main(void)
{
    unsigned char pipeData[] = {0xA2, 0x01, 0x20, 0x04, 0xD2, 0x14, 0x50, 0x04};
    deserialisation(pipeData, sizeof pipeData / sizeof pipeData[0]);
    return 0;
}

Output:输出:

A_SET cmd: 0xA2 0x01 0x20 0x04 
A_DUMP cmd: 0xD2 0x14 0x50 0x04 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM