关于Socket编程,我之前一直处于小数据传输的阶段,就像什么多人聊天之类的,这几天项目碰到了要做在线更新,就想着肯定要静静的写一个非文字信息传输的Socket程序
难点在于:
1、Socket编程中,发送数据和接受数据都需要声明一个缓冲区来存放数据,这个缓冲区的大小设置有讲究,大了可以提高数据传输效率,但是会增加丢包、粘包等现象,小了数据传输效率低,速度减慢并且程序计算量增大
2、一个大的文件不可能直接声明和他大小一样的缓冲区,必须要分包发送,这样字节数据的分割有讲究,最少效率不能拖后腿,影响全局传输速度
3、对于一个大的数据来说,分割成小的数据包后,对于服务器或者客户端来说都是零散的数据,并不知道当前传来的包是干嘛的,这时候每个数据包里应该都设计好数据协议,用来保证每个包正确的完成他的功能
首先解决第一个问题
缓冲区大小的设定,在我的程序里我是根据TCP协议(毕竟我的通信协议是TCP)的数据包大小来设定的,虽然不知道这样会不会对传输速度有实质性的改变,但总比猜出一个数字来要好一点,TCP数据包的最大容量是1492 - IP头(20) - TCP头(20) = 1452(BYTES),我的代码里减掉两个字节当做后面提到的协议位,剩下1450B来当数据位,这样程序的头就出来了(当然我这里直接封装成类了)
之后再来解决第二个问题,关于字节数据的分割,看上面的代码我们知道每个包已经定为1450B,也就是说当传入一个数据时,要根据这个数为单位分割成多个小数据包(比如10M的文件,就会分成7232个包,最后一个包肯定不是满的),这里直接上代码,原本以为用For还是会影响效率,但运行起来还是挺不错的,For循环里用Array类去操作字节数组保证了效率
最后就要解决最难的一个问题了,协议
在我的这个类里,我把协议分成两个字节放在了数据包的前两位,第一位表明这个包的状态,具体说明在PackageState枚举内,第二位表明这个包作用,具体说明在PackageAction枚举内,然后我就直接上枚举,这个枚举可以根据具体使用情况来定制
好了,基本到这里的话Socket分包的核心问题都已经解决了,接下来就是该怎么发怎么收了,这个类的完整代码在下一篇文章发出