2

该循环应该逐行从套接字中获取数据并将其放入缓冲区中。出于某种原因,当没有新数据要返回时,recv 返回它得到的最后几行。我可以通过注释掉第一个 recv 来阻止这个错误,但是我不知道下一行会有多长时间。我知道这不是一个

while(this->connected){
    memset(buf, '\0', sizeof(buf));
    recv(this->sock, buf, sizeof(buf), MSG_PEEK);           //get length of next message
    ptr = strstr(buf, "\r\n");
    if (ptr == NULL) continue;
    err = recv(this->sock, buf, (ptr-buf), NULL);    //get next message

    printf("--%db\n%s\n", err, buf);

    tok[0] = strtok(buf, " ");
    for(i=1;tok[i-1]!=NULL;i++) tok[i] = strtok(NULL, " ");

//do more stuff
}
4

4 回答 4

1

您的问题是,当您将 recv 与 MSG_PEEK 一起使用时,您正在为 recv 提供缓冲区的整个大小,如果已经有两行,例如 "HELLO\r\nHELLO\r\n",它会将它们读入您的缓冲区。

ptr 将指向第一个 \r\n,然后您使用 (ptr - buff) 调用 recv,这将使 recv 仅将第一个 HELLO 读入 buf,但由于您已经将该信息读入 buff,您将处理这两个行,但将 \r\nHELLO\r\n 留在队列中,因为您没有完全阅读它们。

下一次你会偷看它并且挂着你已经处理过的信息,让你相信你得到了重复的数据。

(我希望我写得足够清楚,这是一个非常令人困惑的错误:)

于 2010-04-28T09:35:17.040 回答
1

我需要将 2 添加到第二个 recv 的长度,所以我会采用“\r\n”。否则,它看到第一个 "\r\n" 并认为结尾的行是 buf[0]。

于 2010-04-28T10:14:31.060 回答
1

手册指出:

MSG_PEEK 此标志使接收操作从接收队列的开头返回数据,而不从队列中删除该数据。因此,后续的接收调用将返回相同的数据。

所以我认为你得到了正确的行为,但也许期待别的东西。

于 2010-04-28T09:15:49.093 回答
0

嗨,我找到了解决方案:

void receiver(int accepted_client) {
// Ready to receive data from client.
while (true) {
    char buffer[256];
    recv(accepted_client, &buffer, 255, 0);
    int sum = 0;
    for (int i = 0; i < 256; i++) // Check that buffer value is zero or not.
        sum |= buffer[i];

    if (sum != 0) {// If buffer value is not zero then start to print the new received message.
        string string_message(buffer);
        cout << string_message << endl;
    }
    memset(&buffer, 0, 256); // Clear the buffer.
  }
}
于 2017-11-07T20:19:33.633 回答