0

在进行一些令我困惑的套接字编程时,我遇到了一些奇怪的行为。我从服务器获得了成功的响应,最终程序完全执行。但是,执行一部分逻辑大约需要一分钟。这是它的样子:

int j = 2;
char buffer[BUFFER_SIZE];
char *response;

response = (char*)malloc(BUFFER_SIZE);

while(read(fd, buffer, BUFFER_SIZE - 1) != 0) {
    if(j == 2)
        response = strcpy(response, buffer);
    else
        response = strcat(response, buffer);

    response = (char*)realloc(response, BUFFER_SIZE * j);
    j++;
    bzero(buffer, BUFFER_SIZE);
}

fprintf(stderr, "%s", response);

为什么执行需要这么长时间?谢谢你的目光!

4

2 回答 2

2

我严重怀疑 strcpy/strcat 逻辑是什么在折腾你的表现,但它不是必需的,也没有必要。跟随不断地将数据直接附加到响应缓冲区,该缓冲区随着每次迭代而不断增加。理想情况下,这将增长几何(例如,为下一次读取提供的缓冲区空间与已读取的大小相结合),但对于此示例,逐帧解决方案就足够了。

最重要的是,这利用了read它的返回值:错误通知、数据结束或消耗八位字节的实际计数的三重奏。使用时要记住这一点至关重要read。任何大于零的东西意味着我们读取了一些东西,任何小于或等于零的东西都意味着没有更多的数据(0),或者同步套接字上的错误状态(<0)。

反正:

char *response = malloc(BUFFER_SIZE);
if (response)
{
    ssize_t n = 0, size = 0;

    while ((n = read(fd, response + size, BUFFER_SIZE-1)) > 0)
    {
        size += n; // accumulate data just-read

        // make space for the next frame
        void *tmp = realloc(response, size + BUFFER_SIZE);
        if (tmp == NULL)
        {
            // failed to realloc. break now.
            perror("Failed to realloc response buffer");
            break;
        }

        // otherwise, retain new pointer and march on.
        response = tmp;
    }

    // terminate the buffer. there will always be room
    response[size] = 0;

    // do with the response whatever you will.
    fprintf(stderr, "%s", response);
    free(response);
}

反正就是这样。

如果这不起作用,那么问题出在客户端、服务器或两者之间的管道上的 IP 堆栈上。

于 2020-04-07T04:59:47.750 回答
0

首先,您应该确保第一个strcpy()有正确的字符串可以使用。这可以通过首先将缓冲区初始化为零(就像您bzero()对后续迭代所做的那样)或让

buffer[return_val_of_read] = '\0';

就目前而言,你有可能的UB。

如果这不能解决问题,我会检查 BUFFER_SIZE 是否适当大;如果它像 3 个字节这样奇怪,你可能有太多reallocs()

旁注:
1)评论很重要。read()我将通过允许读取BUFFER_SIZE字节并检查其返回值以了解何时停止来消除中间缓冲区并转储对 C 字符串要求的依赖。这也可以让你摆脱bzero()电话。
2)目前,如果服务器发送的字节数少于BUFFER_SIZE,你有一个不必要的realloc()
3)不要转换结果malloc()

于 2020-04-07T00:12:54.410 回答