日期:2014-05-20  浏览次数:20800 次

求高手点拨一个Java Socket网络传输的“数据完整性”解决方案.
高手,我是一名学习Java的新手,现在我有了:“在网络中传输对象序列化流”的开发需求.
      听到一位前辈说:
      实际的网络是有抖动的,如果进行二进制流的传输,会有:
      整个数据可能发生错乱或者不完整的问题出现.
      希望得到高手的相助:
      如果我把一个对象序列化成为二进制流后,在不用协议的场景下,我应该怎么做,能够让我的代码具备:“接收发出方的数据”“并且无丢失”“按照顺序接收完整”?
      初步的想法是:
      发起方发出总长度,如果接收方接到的数据不到要求的长度,就不回复约好的报文,发出方就再发一遍.
      希望能够有达人,为小弟我贴上代码样例供小弟我参考.
      谢谢达人!!谢谢高手!!

------解决方案--------------------
1、对于你说的错乱和不完整的问题,这指的是采用UDP协议会出现这种问题,你可以采用TCP/IP协议,则不存在这个问题

2、如果你的网络环境要求必须采用UDP协议的话,则可以在每个包的前端加入包在整个数据流中的位置信息,对方收到后,回复位置信息,如果超过1秒(根据你的网络环境自行设置)未收到回复,则重新发送。接收方根据接收到的信息进行合成。

在网络中传输对象,为啥不用java的rmi,用rmi超级简单,根本什么都不用考虑,当然rmi是基于TCP/IP协议的。
------解决方案--------------------
首选,要选对底层的传输协议,我们程序中用到的自定义的协议,都属于应用层的协议。
传输层的协议,现在可以选择 TCP协议,或者UDP协议。
UDP协议,会存在楼主所说的那些担忧,比如,丢包、先后包次序颠倒等现象。
TCP协议,相对好些,它正常情况下是不会丢包的、先后顺序也不会颠倒,但是,读取数据的时候,要注意粘包和半包的处理。

推荐使用TCP协议作为承载协议来传输数据,因为它是有链接的,可靠的传输协议。

应用层协议,可以自己定义协议的数据结构。
比如:发送数据包的时候,包结构分为 包头、包体和包尾三个部分。三个部分依次进行发送,发送完毕,作为一个包的整个内容。
包头存放 包体长度、包序列号(用于区分是否是相同的包,每个包,前后逐个加一构成一个序列)、包类型(这个可以没有)。
包体存放传输的数据(如果包头中没有包类型数据,那么数据区最好有标明数据类型的信息,这样接收端好处理)。
包尾存放固定长度的校验码(这个可以没有,因为TCP传输数据是可靠的),用于校验数据是否在传输过程中被更改了或传错了。如果校验码不是固定长度的,那么,包头中要添加包尾长度的数据字段。

基本上,一般的通讯协议都这么定义数据结构。

其余部分,就是传输过程中的一些处理细节了。
比如:发送数据后是否要求对方做出应答(一般都要有应答包,这样可以相互协作),应答包的超时是多长时间,如果超时是否进行重传,重传时序列号不变(序列号在重传时起作用,接收端可以判断是否是重传包),重传几次算传输失败等等。