我已经阅读了这个关于套接字同步的问题,但我仍然不明白。
最近我正在开发一个相对简单的客户端/服务器应用程序,其中通信通过 tcp 套接字进行。客户端是用 PHP 编写的,使用类似 C 的函数(尤其是fsockopen
和fgetc
)PHP 提供与套接字交互,服务器是用 node.js 编写的,Stream
用于输出数据。
协议非常简单,消息只是一个以 0 字节字符结尾的字符串。
基本上它是这样工作的:
SERVER: Message 1
CLIENT: Ack 1
SERVER: Message 2
CLIENT: Ack 2
....
这真的很好用,因为我的客户一次处理一条消息,方法是从套接字读取一个字符一个字符,直到遇到一个表示消息结束的 0 字节。然后客户端向服务器写回它已成功接收到消息(这就是Ack <message id>
部分)。
现在发生了这样的事情:
SERVER: Message 1
CLIENT: Ack 1
SERVER: Message 2
CLIENT: Ack 2
SERVER: Message 3
Message 4
Message 5
Message 6
CLIENT: <DOH!>
....
这意味着服务器意外地在一个“批次”中向客户端发送了多条消息,尽管每条消息都是服务器上的单个stream.write(...)
操作。似乎消息在某处缓冲,然后立即发送给客户端。我的客户端代码无法在没有响应的情况下处理套接字中的多条消息Ack
,因此它切断了 id 3 之后的剩余消息。
所以我的问题是:
- 套接字的读写同步程度如何?从上面的问题我了解到一个套接字基本上是两个单向管道,这意味着它们根本不同步?
- 一些消息以简单的“一条消息一确认”方式发送到我的客户端,然后突然将多条消息写入流,怎么会发生这种情况?
- 如果套接字以阻塞/非阻塞方式打开,它实际上会改变图片吗?
我使用 PHP 5.4 和节点 0.6.x 在 Ubuntu VM 上对此进行了测试(因此没有负载或任何可能引起奇怪行为的东西)。