如何清理使用 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;
}
我有一个大学项目,我必须在其中实现一个迭代服务器。
服务器使用教授给出的协议,简而言之,客户端必须以特定形式发送消息,我的服务器必须进行一些解析,以便将一些数据保存在全局结构中。
我使用函数 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;
}