【问题标题】:How do I determine if I'm done read()ing from a UNIX socket?如何确定我是否已从 UNIX 套接字读取()?
【发布时间】:2010-02-26 16:48:38
【问题描述】:

我一直在阅读 read(2) 的手册页,根据手册页,read(2) 的返回值为错误时 -1,EOF 时为 0,读取的字节数为 > 0 .

如何判断客户端上的 write(2) 何时完成?

我问是因为我正在编写一个服务器和一个客户端来测试它,但是当我第一次读取(2)并循环检查更多时,读取(2)阻塞并等待另一个写入(2)来自客户端(不会出现,因为我的客户端只有一个 write(2))。

如果我只是遗漏了一些简单的东西,有人可以指出它或给我一个好的参考吗?

【问题讨论】:

标签: sockets unix


【解决方案1】:

客户端需要在完成后关闭套接字。一旦客户端关闭了套接字,服务器就会收到 EOF 消息。如果客户端保持套接字打开但从不写入,服务器将永远等待另一条消息下来。

【讨论】:

  • 当客户端和服务器有多个读/写时怎么办?我是否必须按照诺亚的建议开始使用标题?
  • 您真的不应该仅仅为了接收一条消息而关闭套接字。我认为贾斯汀的回答是正确的方式。
  • @Chaos,我理解 OP 只 想要 发送/接收一条消息。 @Alex,如果您想接收多条消息,那么您可以按照 Noah 的建议使用信令,在当前消息中的字节数前面加上一个标头,或者使用面向消息的协议。
【解决方案2】:

read 返回时你知道你已经完成了:

  • -1 - 发生错误
  • 0 - EOF
  • 另一个非零值 - 这是最常见的情况。您的协议需要使用 header 指定消息大小或 固定长度消息 来指定其消息的大小。然后您可以跟踪读取的字节数,并且您知道一旦读取了那么多字节就完成了。否则,您需要继续读取字节,直到收到完整的消息。

【讨论】:

  • 所有这些都在问题中说明。
  • @Chaos - 没错。 @noah - 提到了前两个,但没有提到最后一个(也是最重要的!)子弹。关键是您需要另一种策略来从套接字读取多条消息。除了我描述的方法之外,您还可以按照您的建议使用分隔符,但有一些注意事项。
【解决方案3】:

读取和写入之间没有对应关系。单个客户端写入可能需要 10 次读取才能完全加载。除非您在内容中放置分隔符,否则您无法知道结束在哪里,除非套接字已关闭。

如果还需要给客户端发送响应,可以在客户端半关闭socket:

shutdown(socket, SHUT_WR);

这将导致服务器上的读取返回 0。

【讨论】:

  • 您建议使用哪种分隔符?你怎么知道分隔符不会也出现在消息数据中?
  • 我认为他的意思类似于空字符。 (如果您要发送文本。)
  • 你可以使用任何你想要的分隔符,只要它在数据中正常出现时客户端将其转义即可。但除非需要保持连接保持打开状态,否则(一半)关闭套接字是更好的选择。
【解决方案4】:

需要注意的是首先使用select() 来检查数据,并指定一个合适的超时时间,而不是盲目地调用read()。这将允许您的服务器在一段时间不活动后关闭套接字,并释放它可能使用的任何资源等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-18
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    相关资源
    最近更新 更多