Sockets 套接字是否同步?

Sockets 套接字是否同步?,sockets,unix,language-agnostic,Sockets,Unix,Language Agnostic,我已经读过了,但我还是不明白 最近,我正在开发一个相对简单的客户机/服务器应用程序,其中通信通过tcp套接字进行。客户端使用PHP提供的类似C的函数(特别是and)用PHP编写以与套接字交互,服务器使用node.js编写以输出数据 协议非常简单,消息只是一个以0字节字符结尾的字符串 基本上它是这样工作的: SERVER: Message 1 CLIENT: Ack 1 SERVER: Message 2 CLIENT: Ack 2 .... 这确实很好,因为我的客户机一次处理一条消息,从套

我已经读过了,但我还是不明白

最近,我正在开发一个相对简单的客户机/服务器应用程序,其中通信通过tcp套接字进行。客户端使用PHP提供的类似C的函数(特别是and)用PHP编写以与套接字交互,服务器使用node.js编写以输出数据

协议非常简单,消息只是一个以0字节字符结尾的字符串

基本上它是这样工作的:

SERVER: Message 1
CLIENT: Ack 1

SERVER: Message 2
CLIENT: Ack 2

....
这确实很好,因为我的客户机一次处理一条消息,从套接字逐字符读取消息,直到遇到一个0字节表示消息的结尾。然后,客户端向服务器回写它已成功接收消息(这是
Ack
部分)

现在发生了这样的事情:

SERVER: Message 1
CLIENT: Ack 1

SERVER: Message 2
CLIENT: Ack 2

SERVER: Message 3
        Message 4
        Message 5
        Message 6
CLIENT: <DOH!>
....
服务器:消息1
客户:Ack 1
伺服器:讯息2
客户:Ack 2
伺服器:讯息3
信息4
信息5
信息6
客户:
....
这意味着服务器在一个“批处理”中意外地向客户端发送了多条消息,尽管每条消息都是服务器上的单个
流。write(…)
操作。消息似乎被缓冲在某个地方,然后立即发送到客户端。我的客户端代码无法处理套接字中的多条消息,中间没有
Ack
响应,因此它会切断id 3之后的剩余消息

所以我的问题是:

  • 套接字的读写同步程度如何?从上面的问题中,我了解到插座基本上是两个单向管道,这意味着它们根本不同步
  • 一些消息以简单的“一条消息一个确认”的方式发送到我的客户机,然后突然将多条消息写入流,这怎么会发生呢
  • 如果插座以阻塞/非阻塞方式打开,它是否会改变画面

我使用PHP5.4和node 0.6.x在Ubuntu VM上测试了这一点(因此没有负载或任何可能引起奇怪行为的东西)。

TCP是双向流的抽象,因此没有消息的概念,也不能保留消息边界。无法保证多个send()或recv()调用将如何映射到TCP数据包。您应该将send()视为多次调用它相当于将所有数据串联在一起调用一次。更重要的是,在接收数据时,您应该确保您的代码以完全相同的方式解释传入的数据,无论它是如何通过individual recv()调用分割的

要正确接收,可以使用缓冲区存储未完成的消息。但请注意,当缓冲区中存在不完整的消息时,下一个recv()调用可能会完成当前消息,并提供零条或更多完整消息,可能还会提供另一条不完整消息的一部分


阻塞或非阻塞模式在这里不会改变任何东西-它只是关于应用程序与操作系统的接口方式。

有两个同步概念需要处理:

  • send()
    recv()
    的(通常)同步操作
  • 一个进程发送消息和另一个进程处理消息的异步方式
  • 如果可以的话,尽量避免让进程中的客户机和服务器彼此保持同步的“锁定步骤”。那是自找麻烦。如果其中一个进程意外关闭怎么办?另一个进程/线程可能挂起一个永远不会出现的
    recv()
    。对于您的设计来说,期望最终确认每条消息是一回事,但是对于您的设计来说,期望只能发送一条消息是另一回事,在发送另一条消息之前,必须先确认它

    考虑这一点:

    Server: send 1
    Client: ack 1
    Server: send 2
    Server: send 3
    Client: ack 2
    Server: send 4
    Client: ack 3
    Client: ack 4
    
    能够适应这种情况的设计比预期的更好:

    Server: send 1
    Client: ack 1
    Server: send 2
    Client: ack 2
    Server: send 3
    Client: ack 3
    Server: send 4
    Client: ack 4
    

    更不用说,一次只有一条消息“在传输中”,您就失去了管道传输的所有好处,因此协议的速度将受到网络延迟的严格限制。。。