如何解决使用套接字时被分解的邮件?

时间:2015-02-13 02:14:19

标签: java php sockets tcp bitstuffing

我的设计

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

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

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

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

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

关注

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

问题

这是我需要考虑的事情吗? 如果是,怎么样?

可能的解决方案

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

2 个答案:

答案 0 :(得分:2)

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

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

2)以每个消息的长度作为前缀。

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

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

答案 1 :(得分:1)

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

这里最常见的两种方法是:

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

    使用此方法的一些协议包括SMTP,IMAP和IRC。

  2. 在标题中包含邮件的长度,以便您知道要读取的数据量。

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

  3. 如果您不确定采用哪种方法,第二种方法实施起来要容易得多,并且不会对您使用它的数据施加任何限制。一个简单的实现可能只是将字节数存储为压缩整数,并且看起来像下面的伪代码:

    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()方法将阻塞,直到发送或接收整个消息。当然,您的代码必须使此工作正常。)