在C中读取和解析不同长度的数据帧

时间:2018-04-17 15:37:30

标签: c

我正在编写一个从Linux上的tcp套接字读取帧的程序,我正在努力正确地读取数据,因为帧长度不同。 框架看起来像这样:

|start   | length  | Data (contains "hello")      |
|0x81    | 0x05    | 0x48 0x65 0x6c 0x6c 0x6f     |
|1 byte  | 1byte   | 5 bytes                      |
---------------------------------------------------

我面临的挑战是弄清楚完整帧何时被引入缓冲区并识别下一帧的开头是否已部分重新进入缓冲区。在这种情况下,我需要

  1. 处理完全退回的框架
  2. 我需要从缓冲区中删除已处理的帧
  3. 继续读取套接字,直到最后一帧被完全重新处理以进行处理
  4. 到目前为止我的代码:

    int processdata(char **frame, int64_t *readedLength, int64_t clientsock) {
          char *pframe = *frame;
          if (( *readedLength) < 2) {
            //we need at least 2 bytes to be able to determine the frame length
            return 0;
          }
    
          int64_t len = pframe[1]; // the second byte of the frame contains the length
          if (len <= ( *readedLength)) {
            //we have readed the complete frame -> print to console
            //...
          }
    
        //if we have readed more than the length of the frame, we started reading already the next frame.
          //check how many bytes we readed from the next frame
          int64_t lengthRemainingBuffer = ( *readedLength) - (len-2);
          if (lengthRemainingBuffer == 0) {
            //no next frame available. Lets still create new empty buffer for next socket read. 
            char *nextFrame = malloc(sizeof(char) * 1); 
            *frame = nextFrame;
          } else {
            //we started reading the next frame. Lets create a new buffer with it   
            char *nextFrame = malloc(sizeof(char) * lengthRemainingBuffer); 
            *frame = nextFrame;
          }
          //update the buffer counter
          ( *readedLength) = lengthRemainingBuffer;
          return 0;
        }
    
        int main() {
          char *incoming = malloc(sizeof(char) * 1); //initialize read buffer pointer
          int64_t incoming_length = 0;              //initialize variable to store readed bytes
          /* Setup epoll structures....*/
          //...
          /* The event loop */
          while (1) {
            int64_t count;
            char buf[2]; //reading only 2 bytes
    
            count = read(events[i].data.fd, buf, sizeof buf);
            if (count > 0) {
              //we have data, add it to buffer
              incoming = realloc(incoming, sizeof(char) * (incoming_length + count));
              memcpy(incoming + incoming_length, buf, count);
              incoming_length = incoming_length + count;
            }
            //...
            //lets process the data -> check if we have readed complete frame. If yes: print to console, if not continue reading until we have complete frame
            processdata( & incoming, & incoming_length, events[i].data.fd);
          }
          //...
        }
    

    这是好习惯吗?难道我做错了什么? 我很感激任何提示。

    Barmar :&#34;我们至少需要4个字节&#34; - 为什么? 2个字节就足够了 - &gt; 是的,你是对的。我修好了。

    chux :if(len&lt; = readedLength){应该导致编译器警告。 - &gt; 正确。当我将代码缩减到相关部分时,这只是一个错字。

    jaco0646 :此问题属于codereview - &gt; 这只是代码的一小部分,导致高负载下的分段错误。所以它不起作用。我相信问题依赖于我在这里发布的缩减代码。

    Barmer :为什么不在从套接字读取时检查长度,而不是在处理缓冲区时?如果它表示长度= 5,则只读取接下来的5个字节。 - &gt; 数据框可能变得非常非常大。所以我不能保证在读完长度之后我能够立刻读完整个画面。有时套接字不会立即提供完整的框架。所以我需要每次检查我已经阅读了多少,还有多少仍然缺失。这就是我正在做的processdata函数。

0 个答案:

没有答案