如何清理使用 read() 填充的缓冲区并继续读取同一缓冲区?

How to clean a buffer filled using read() and continue reading at the same buffer?

我有一个大学项目,我必须在其中实现一个迭代服务器

服务器使用教授给出的协议,简而言之,客户端必须以特定形式发送消息,我的服务器必须进行一些解析,以便将一些数据保存在全局结构中。

我使用函数 read() 来接收消息并将其存储在固定大小的字符数组中。我的问题是消息有时可能比我用来存储它的缓冲区的大小更大。 注意:为了绕过这个问题,我无法先发送消息的大小。

我想知道是否有办法做到这一点。

下面是部分代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "keyvalue.h"
#include <errno.h>

int main ( int argc, char *argv[])
{
    char keyvaluebuffer[4096];
    int num;
    //socket()
    //bind()
    //listen()

    while(1)
       {
           //accept()
           while((num = read(acceptfd, keyvaluebuffer, 4096) ) > 0 )
              {
                  //At this point I use the keyvaluebuffer to parse it and store the data.
              }//while (read > 0) end
           if (num < 0){close(accept);}

           close(accept);
      }//while(1) end       
   close(socket);   
}//main end 

如果消息大于缓冲区大小,那么在读取更多消息之前,您至少需要存储已检索到的消息部分。一种选择是动态分配消息缓冲区。在将部分消息读入静态缓冲区后,它被复制到动态消息缓冲区中。如果动态消息缓冲区已满,则重新分配。

在下面的示例代码中,buffer[] 是一个包含 BUF_SIZE char 的数组。 msg 是指向动态分配内存的指针,最初指向 BUF_SIZE 字节。 msgbuff_sz 跟踪动态消息分配的大小,而 msg_sz 跟踪实际消息大小。每次调用 read() 后,buffer[] 的内容将复制到 msg 中的适当位置,并更新 msg_sz。如果消息大小与消息缓冲区大小相同,则重新分配消息缓冲区 msg。这一直持续到达到文件结束条件(或直到 read() returns 一个错误值)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#define BUF_SIZE  4096

int main(void)
{
    int fd = open("message.txt", O_RDONLY);
    if (fd < 0) {
        perror("Unable to open file");
        exit(EXIT_FAILURE);
    }

    char buffer[BUF_SIZE];
    char *msg = malloc(BUF_SIZE);
    size_t msgbuff_sz = BUF_SIZE;
    size_t msg_sz = 0;

    if (msg == NULL) {
        perror("Buffer allocation error");
        exit(EXIT_FAILURE);
    }

    ssize_t ret_val;

    while ((ret_val = read(fd, buffer, sizeof buffer)) > 0) {
        memcpy(msg + msg_sz, buffer, ret_val);
        msg_sz += ret_val;
        if (msg_sz == msgbuff_sz) {
            msgbuff_sz += BUF_SIZE;

            char *tmp = realloc(msg, msgbuff_sz);

            if (tmp == NULL) {
                perror("Buffer reallocation error");
                exit(EXIT_FAILURE);
            }
            msg = tmp;
        }
    }

    if (ret_val < 0) {
        perror("Unable to read file");
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < msg_sz; i++) {
        putchar(msg[i]);
    }
    putchar('\n');

    free(msg);

    return 0;
}