0

我的设计

我正在使用套接字来实现聊天服务器。

客户端使用 Java 的java.net.SocketBufferedReader从服务器读取消息。

服务器端使用 Php 的socket_read()从客户端获取消息。

它使用 Php 的socket_write()从服务器发送消息。socket_write() 不保证整个原始消息都会被写出,这意味着我可能需要多次调用它才能发出整个原始消息。

(在设计方面,客户端向服务器发送消息,服务器将这些消息重新路由到适当的客户端。)

关注点

我担心的是一条消息可能会被分解成几个较小的消息。所以当服务器或客户端读取传入的消息时,它实际上可能是原始消息的片段。

问题

这是我需要考虑的事情吗?如果是,如何?

可能的解决方案

现在我正在考虑使用字节填充(这是一种网络技术,用于将字节插入原始消息中,作为标志在发送消息之前标记消息的开始和结束)。

4

2 回答 2

2

如果您需要应用程序级别的消息,那么您必须在应用程序级别实现它们。有几种常见的方法:

1) 使用固定长度的消息。

2) 在每条消息前面加上它的长度。

3) 使用自然不会出现在您的消息中的“消息结束”标记。

4) 使用“消息结束”标记,如果它出现在您的消息中,则将其转义。

于 2015-02-13T02:33:30.353 回答
1

是的,这是您需要在协议中处理的事情。

这里最典型的两种方法是:

  1. 使您的协议面向行。用换行符终止每条消息,并且在看到换行符之前不要将一行视为完整。当然,这取决于消息中没有自然出现的换行符。

    使用这种方法的一些协议包括 SMTP、IMAP 和 IRC。

  2. 在其标头中包含消息的长度,以便您知道要读取多少数据。

    使用这种方法的一些协议包括 HTTP(在Content-Length标头中)和 TLS,以及许多低级协议,例如 IP。

如果您不确定采用哪种方法,则第二种方法更容易实现,并且不会对您使用的数据设置任何限制。一个简单的实现可能只是将字节数存储为压缩整数,并且可能类似于以下伪代码:

send_data(dat):
    send(length of dat as packed integer)
    send(dat)

recv_data():
    size = recv(size of packed integer)
    return recv(buffer)

(此代码假定抽象send()recv()方法将阻塞,直到发送或接收整个消息。当然,您的代码必须适当地进行此工作。)

于 2015-02-13T02:54:09.033 回答