写在前面
最近一个多月一直在弄文件传输的组件。最近也有个基本的样子了,这里算是一个简单总结吧。
中转模型
文件传输底层使用开源的c++通信组件hp-socket(Pullserver,pullClient)。感兴趣的可以搜一下。
废话不多说,进入正题
首先,所有的客户端必须首先登陆服务器,在服务器进行注册,在服务器端维护一个客户端标识与客户端信息的映射关系,比如客户端信息类ClientInfo。
//代码片段 ClientInfo { IntPtr connID; string ip; ushort port; }
则服务端,就需要有这样一个类似Dictionary<string,ClientInfo>的字典。在客户端A给客户端B转发数据的时候,可以从这个映射关系中找到对方。
登录过程
在客户端登录成功后,就可以发送文件了。
包头信息说明
TransferId:传输id,标识在同时传输多个文件时,是不同的传输。
TransferType:传输类型
TransferCommand:传输命令
MD5:检验值(md5或者hash,越短越好,算法越快越好)
FileName:文件名。
FileRelativePath:传输文件夹时用到,文件夹中的文件,需要用到相对路径,接收端根据接收路径+相对路径进行保存文件夹中的文件。
Size:文件或者文件夹总大小,将总大小抛给应用层,计算传输速度。
currendIndex:当前传输包的索引,也是读取文件第几个包的索引。
PkgCount:总共多少个包。接收端可以根据当前索引和包总数,来判断是否传输完成,或者在断点续传的时候用到。
From:发送端标识
To:接收端标识
BodySize:每次传输的body大小。
自定义协议
固定包头+Body
每次包都要遵循该协议,服务器收到包后,要进行解析,根据包头中bodysize取出这次的数据Data。
断点续传
在接收端,每次接收到包,写入文件的同时,将包头信息写入本地文件(ini也好,xml文件也好)。然后发送端,再次发送该文件的时候,首先会发送请求包,接收端根据该文件的包头信息和ini文件中的信息,比对md5是否相同,发送方是否相同,如果相同,则将CurrentIndex+1,响应给发送端。发送端就可以直接从CurrendIndex+1的位置继续读取文件包进行发送。
总结
该组件前前后后大概一个多月,里面业务比较复杂,需要考虑的到的东西还是比较多的,目前实现,同时传输多个文件,多个文件夹,断点续传功能。但多文件和多文件夹同时混合发送仍有问题。还有客户端A给客户端B发送文件的同时,客户端B给客户端A发送,仍有问题。
通过该组件的设计,也收获不小,对业务能力也是一种考验。对tcp通信有了更深入的学习。
本文只是分享一下思路,感兴趣的可以搜一下hp-socket。