【问题标题】:c web server client response gets cut out by read()c Web 服务器客户端响应被 read() 截断
【发布时间】:2021-12-20 22:59:33
【问题描述】:

我正在使用 C Web 服务器,当我向服务器发送发布请求时,只有部分发布响应被传递到服务器,其余部分丢失。我很确定问题不在于缓冲区大小。可能是数据没有及时发送,但我不知道。下面是在服务器上接收数据的代码:

while ((readSock = read(acceptSock, recvLine, sizeof(recvLine))) > 0) {
    if (readSock < 0) {
        printf("readSock error\n");

        memset(fileDir, 0, 255);
        memset(recvLineGET1, 0, 70);
        memset(httpResponseReport, 0, 1000);
        memset(recvLineGET, 0, 60);
        memset(fileLine, 0, 1);
        memset(httpResponse, 0, 1000);

        close(acceptSock);
        return NULL;
    }

    fprintf(stdout, "%s", recvLine);

    if ((endOfPost = strstr(recvLine, "\r\n\r\n")) != NULL) {
        splitPost = strtok(endOfPost, "&");
            
        while (splitPost != NULL) {
            printf("%s\n", splitPost);
            splitPost = strtok(NULL, "&");
        }

        printf("newline detected\n");
        break;
    } else if (readSock <= 0 && endOfPost == NULL) {
        perror("endOfHttpBody error");

        memset(fileDir, 0, 255);
        memset(recvLineGET1, 0, 70);
        memset(httpResponseReport, 0, 1000);
        memset(recvLineGET, 0, 60);
        memset(fileLine, 0, 1);
        memset(httpResponse, 0, 1000);

        close(acceptSock);
        return NULL;
    }

    memset(recvLine, 0, 10);
}
memset(recvLine, 0, 10);

【问题讨论】:

  • 定义“被剪掉”。另外,您所说的是 request 还是 response 的一部分?那是客户端的代码还是服务器的代码?你能提供一个minimal reproducible example吗?请展开。
  • 好吧,您还没有定义“响应被切断”的含义。 1)如果是服务器,那么它是请求,而不是响应......和2)更详细地解释“cut”。此外,再一次,minimal reproducible example 会更好。在任何情况下,进行部分读取然后strstr(recvLine, "\r\n\r\n") 很容易失败,因为您可以很好地接收拆分为两个不同读取的数据(例如,一个带有\r,另一个带有\n\r\n)并且不匹配他们。
  • @MarcoBonelli 例如,假设我有一个像“username=username123&password=password123”这样的响应被发送到服务器进行处理,我所说的“响应被切断”的意思是我会收到一些东西比如:“用户名=用户?”。另外,如果回复部分被读取,我将如何在回复末尾捕获"/r/n/r/n"?
  • (1) 那么这是一个短读,你需要一个或多个读来获取其余的数据 (2) 将所有内容存储在一个缓冲区中然后检查,或者增量检查但仍然存储数据仅在一个缓冲区中,将所有接收到的片段放在一起。
  • @MarcoBonelli 如果可行,我会尝试并更新您。

标签: c sockets post webserver


【解决方案1】:

您不能依赖这样一个事实,即使用“足够大”的缓冲区大小调用 read() 实际上会一口气读取所有响应。 你必须在一个循环中调用 read() ,直到你得到所有的响应。 TCP 套接字上的 read() 调用无法保证您将读取多少数据。您正在获取数据流,系统会将数据作为字节流传递给您,但您无法控制它们如何打包在一起。(这取决于很多事情,在网络堆栈的深处在内核中,所以你不能假设任何东西)。 唯一正确的方法是循环 read() 直到没有更多数据要读取。由您来编写处理代码,以处理在一次 read() 调用中无法获取所有数据。 read() 返回已读取的字节数,因此您可以轻松地再次调用 read() 传递缓冲区指针 + 到目前为止已经读取了多少字节,以便下一次调用 read 将在之后立即将字节放入缓冲区已经存在的数据。如果返回的数据在某个时候更大,您仍然需要进行一些检查以确保不会超出缓冲区的范围。

【讨论】:

  • 您能添加一些换行符吗?这样会更容易阅读。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-01
  • 2016-09-20
  • 1970-01-01
  • 2021-03-18
相关资源
最近更新 更多