【问题标题】:socket TCP: Why do I lose messages with scanf套接字 TCP:为什么我会使用 scanf 丢失消息
【发布时间】:2017-01-01 10:45:27
【问题描述】:

我在 Mac OS 中用 c 创建了一个服务器和一个客户端。
他们所做的很简单:服务器发送消息,客户端接收消息。
但是我不知道为什么,但是当我在scanf 的帮助下输入多条消息时,我总是会丢失一些消息。
以下是主要代码:

// client
char msg[200];
while(1)
{
    if(read(sockclient, msg, sizeof(msg)) <= 0)
    {
        break;
    }
    printf("Message recu: %s\n", msg);
    bzero(msg, 200);
}


// server
while(1)
{
    lg=sizeof(coord_client);
    newsockfd=accept(sockserveur,(struct sockaddr*)&coord_client,(socklen_t *)&lg);
    char msg2[100];
    while(1)
    {
        scanf("%s",msg2);
        write(newsockfd,msg2,sizeof(msg2));
        printf("message envoye\n");
        bzero(msg2, sizeof(msg2));
    }
}


问题是:如果我一一输入消息,例如a&lt;Enter&gt;b&lt;Enter&gt;,一切都很好。但是,如果我一次输入多条消息,我总是会丢失其中的一些。例如,如果我输入a b c d&lt;Enter&gt;,表示我要发送四个消息:abcd,客户端总是可以得到其中三个,c 是miss。但是服务器确实发送了四次,因为我收到了四个message envoye

编辑
我检查了函数read 的返回值,我得到了一些我不明白的东西。

请注意:当read返回200而不是100时,客户端会丢失以下消息。

【问题讨论】:

  • BUF 的大小是多少?一侧有 100 个,另一侧有 BUF
  • 你应该检查read()的返回值。它可能不会返回整个消息大小,它允许返回小于您指定的值。
  • 另外,不需要发送整个缓冲区:strlen(msg2)+1 足以发送字符串 + 终止
  • TCP 不保留消息边界,它只是一个字节流。因此,当服务器发送两个 100 字节的消息时,如果请求 200 字节,服务器可以读取它们。
  • 它也可以返回 less 比你要求的。它可能第一次返回 50 个字节,下一次返回 150 个字节,而不是返回 100 个字节。

标签: c linux sockets tcp scanf


【解决方案1】:

嗯,读取 200 个字节但写入 100 个字节很简单。有时在客户端读取之前有两次写入。所以它连续读取了两条消息。

char msg[101];
size_t i = 0;
ssize_t ret;
while (i < 100 && (ret = read(sockclient, msg + i, sizeof msg - i - 1)) <= 0)
{
  i += (size_t)ret;
}
if (i == 100) {
  msg[100] = '\0';
  printf("Message recu: %s\n", msg);
}

【讨论】:

  • i &lt; 100 应该是i &lt; 99,不是吗?
  • @alk 否,因为服务器写入 100 个字节,i 必须表示我们读取了多少字节。我没有测试:p。
  • 您需要为0-terminator 保留空间。所以负载缓冲区实际上是 buffer-size -1 。
猜你喜欢
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 2017-02-11
相关资源
最近更新 更多