gpt4 book ai didi

C - 在 while 循环中直接写入数组,同时使用 recv 接收数据

转载 作者:行者123 更新时间:2023-11-30 14:34:38 26 4
gpt4 key购买 nike

这是我的代码:

FILE *responseStorage = fopen("response", "w");

if(responseStorage == NULL){
//error handling
}

int receivedTotal = 0;
while(1){
ssize_t received = recv(sockfd, buf, BUFSIZ, 0);
if( received == -1 ){
//error handling
}
if( received == 0 ){
//end of stream
break;
}
receivedTotal += received;
if(fwrite(buf, received, 1, responseStorage) != 1){
//error handling
}
memset(buf, '\0', sizeof(buf));
}

fclose(responseStorage);

FILE *responseFile = fopen("response", "r");
char responseArray[receivedTotal];
if(fread(responseArray, receivedTotal, 1, responseFile) == 0){
//error
}

我正在调用ssize_t returned = recv(sockfd, buf, BUFSIZ, 0);,从服务器接收数据,将我收到的数据保存在receivedTotal += returned; 并使用 fwrite(buf, returned, 1, responseStorage) 将该数据写入我的文件 FILE *responseStorage。之后,在流循环结束时,我以 r 模式打开 responseStorage 文件,创建一个大小为 receivedTotal, 的数组>char responseArray[receivedTotal];,并使用 fread(responseArray, receiveTotal, 1, responseFile 将数据从 responeStorage 文件写入 responseArray.

有没有办法直接写入responseArray?我必须稍后验证响应,所以我需要它在一个数组中。我知道我必须使用 malloc 动态分配数组空间。我想避免使用 receivedTotalresponseStorage

最佳答案

您已经从套接字读取 buf ,所以你所要做的就是写 buf动态分配的字符串而不是 responseStorage 。就像你说的,你只有处理内存空间来适应你的响应。

执行此操作的低效但非常简单的方法是在每次读取时重新分配存储。您可以为先前响应读取的总和以及 buf 中的新字符串分配存储空间。 ,然后将两个字符串写入新分配的空间。您知道这些字符串的长度总和 +1 为空字节,因此您不必太担心可用的分配空间。然而,这是相当昂贵的,因为读取会被一遍又一遍地复制。

稍微复杂一点的方法是分配一个可能相当大的主响应字符串缓冲区,跟踪其总分配空间长度并使用 strncat继续连接buf直到它的长度超过响应中的剩余空间,+1(用于终止零字节)。当房间不够时,您可以调用realloc以获得更多内存。 realloc不是很有效(按照 C 标准),因为它可能需要分配不同的空间,复制现有数据,然后返回一个新指针。

如果你想变得更聪明,你可以分配一个大缓冲区,然后发送 read指向缓冲区中下一个可用点的偏移量的指针。您可能仍然需要增加缓冲区,但至少不需要复制它。 buf然后成为你的响应数组。这是我将演示的实现:

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

int main(int argc, char**argv){
size_t size = 2;
size_t len = 0;
char* fullbuf = malloc(sizeof(char)*size);
while(1) {
ssize_t b = read(STDIN_FILENO, fullbuf + len, sizeof(char) * (size - len-1) );
if( b < 0) {
perror("Couldn't read from stdin: ");
exit(2);
} else if( b == 0 ){
break;
}
if( b + len + 1 >= size) {
// time to allocate more memory
size = size * 2;
fullbuf = realloc(fullbuf, sizeof(char) * size);
if( fullbuf == NULL ){
fprintf(stderr, "Couldn't allocate %zd more bytes of memory\n", size);
exit(1);
}
}
len += b;
}
fullbuf[len] = '\0'; //terminating null space
printf("%s", fullbuf);
}

在这个演示中,我从标准输入而不是套接字读取,但想法相同。我只阅读了 buf 中可用的数据。 。当它已满(但终止字节)时,我将其空间加倍。请注意,我设置了 fullbuf到 realloc 的输出 - 它可能是相同的地址,也可能不是。

为了证明它有效,我从相当疯狂的 2 字节缓冲区开始,然后从那里加倍,所以有很多 realloc来电。我抓取了 32k 的 lorem ipsum 作为输入。

$ du -h file.txt
32K file.txt
$ shasum -a 256 file.txt
346f2adbd1fdca6bf3b03fb0a4d2fd0030e3363e9a9c5d1e22747e1bcc316e37 file.txt
$ ./t < file.txt | shasum -a 256
346f2adbd1fdca6bf3b03fb0a4d2fd0030e3363e9a9c5d1e22747e1bcc316e37 -

太棒了,如果 shasum 相同,那就意味着我输出了 file.txt确切地。

关于C - 在 while 循环中直接写入数组,同时使用 recv 接收数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58892484/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com