Java文件同步期间的网络错误。

3
我目前正在开发一个简单的客户端/服务器文件同步。为此,客户端和服务器遵循一种简单的协议来确定发送消息的顺序。
简化的协议(使用Object/ByteArrayStreams):
客户端循环:
1. 发送文件名 2. 发送文件信息 3. 发送数据 4. 等待服务器确认
服务器循环:
1. 读取文件名 2. 读取文件信息 3. 接收数据 4. 向客户端发送确认消息
重复进行上述步骤。
问题在于当传输过程中出现错误时,协议会失序,我通常会收到StreamCorruptedExceptions,因为至少有一方期望得到其他内容。
以下是一个示例问题: 服务器在接收文件(第3个步骤)时出现故障。现在服务器正在等待文件名。由于出现错误,客户端到达第3个步骤并发送了数据。然后抛出异常,因为服务器期望得到一个消息对象,而客户端发送字节数据。
解决这个问题最好的方法是什么?

你在使用基于TCP的协议吗?你能直接在进程内交换对象消息中重现这个错误吗?你有编写任何自定义Externalizable实现吗? - cutchin
也许我在使用“协议”这个词时表达不准确了。实际上,它只是通过Java(Object)流发送消息,如文件名和数据,然后发送确认信息。在测试条件下,我没有遇到这个错误,但在使用过程中可以重现它。 - b1nh
从异常信息来看,你似乎正在使用ObjectInputStream和ObjectOutputStream在类似UDP的“尽力而为”协议上进行通信。是这种情况吗? - Jim Garrison
是的,我正在使用那些流,但它们是通过TCP使用的。 - b1nh
2
文档中提到您的对象流已损坏。您应该发布一小段可编译和可运行的代码片段,以供他人测试。 - blackcompe
抛出一小段代码是没有帮助的,因为这是一个更理论性的问题:如果任何一方发生错误,我如何保持协议同步? - b1nh
1个回答

2

一些想法

  • 也许在每个阶段之后发送确认信息 - 这样更容易控制。
  • 服务器的确认可以发送一个校验和,客户端可以验证交易的完整性并继续进行。(例如md5)。
  • 实现一个“无状态”的服务器 - 即可以根据每个事务开头设置的某个“魔数”来临时决定要服务哪个阶段的服务器(标头)。这样,客户端可以重试任何阶段,服务器将能够相应地响应。
  • 您可以扩展标头以包含唯一文件的唯一id,因此您将能够并行化整个通信,并从多个客户端上传多个文件的多个阶段。

其他想法

  • 如果您想避免问题而不是解决它,您可以使用非常有效的库来代替您完成这项工作,而不是重新发明轮子。查看protobuf - 它很难掌握,但非常高效,gson则非常容易掌握,虽然效率较低,还有许多其他现成的协议。

谢谢你的答案!我选择了无状态服务器,现在它运行得更好了。 - b1nh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接