【问题标题】:When does recv() return?recv() 什么时候返回?
【发布时间】:2014-10-25 14:42:03
【问题描述】:

我已经使用套接字创建了一个服务器和一个客户端。我的服务器是用 c 编写的,运行在我的树莓派上,我的客户端是用 Swift 编写的,运行在我的 Mac/iPhone 上。

当我的服务器 recv() 函数执行我从客户端发送的内容时,我没有得到什么?如果我发送 0-10 个字节,在我关闭连接之前它不会从 recv() 函数返回。但如果我发送 100+ 字节,它会立即执行。

每次我从客户端写消息时,我希望我的服务器从 recv() 返回。

这是我的服务器 recv() 函数:

//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
    printf("%s", client_message);
}

这是我的客户写法:

func SendMsg(msg:String) -> Int{
    return outputStream!.write(msg, maxLength: countElements(msg))
}

除了我无法控制服务器何时执行我的消息之外,一切正常。

【问题讨论】:

  • 我不知道 Swift 是否发送了 C 代码需要的字符串终止符,所以你可能在服务器中有undefined behavior 的情况。
  • 我也用 C 语言制作了客户端。从那里我得到了同样的行为。你在说 \0 结束字符吗?
  • 您确定是 recv 而不是 printf 缓冲数据吗?尝试在printf 格式字符串的末尾添加'\n'
  • 是的,这就是我所说的终止 '\0' 字符。如果客户端不发送,服务器需要添加。
  • 哦,关于@SanderDeDycker 的评论,您必须记住默认情况下输出到stdout行缓冲。添加一个手动刷新输出缓冲区的换行符。

标签: c sockets stream swift recv


【解决方案1】:

stdout 的输出默认为行缓冲,因此在使用printf 时,请确保末尾有一个换行符('\n')。如果消息本身不包含换行符,则:

printf("%s\n", client_message);

附带说明:还要确保client_message 在将其传递给printf 之前正确地以null 终止,否则您可能会遇到未定义的行为(参考@JoachimPileborg 的评论)。如果您不能确保空终止,这也可以解决问题:

printf("%.*s\n", read_size, client_message);

【讨论】:

    【解决方案2】:

    服务器没有收到消息,因为客户端没有发送它。

    你需要fflush客户端的outputStream!

    【讨论】:

    • 我将换行符添加到我的 printf 中,它现在可以工作了。你确定我的客户不发送消息吗?
    • 如果 outputStream 是行缓冲的,那么添加换行符会导致缓冲区刷新(隐式刷新)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 1970-01-01
    • 2021-10-11
    • 2016-09-05
    • 2015-03-15
    • 1970-01-01
    相关资源
    最近更新 更多