关于文件传送类程序的思路和流程(一块板砖)

wangxiangsjz 2003-12-19 06:23:46
经常在BBS上看到关于文件传送的讨论,这里把我的一个用UDP协议写得文件传送程序的有关思路发表出来,以期抛砖引玉。(这里虽然是用UDP协议写的,不过思路同样适用于其它通信方式如串口)。
文件传送的基本思路是把文件分成大小适当的数据块,每一次传送一个数据块。每一块数据有一个校验码,接收方根据校验码校验收到的数据块是否正确无误。同时为了能够保证数据块的正确顺序,还要表示数据块的序号。把有关信息组成一个个数据包,通过发送、接收方的正确处理,保证整个文件传输的快速、准确。
一、 数据包结构:
typedef struct
{
char FileFlage[6]; //标志:文件传送类数据包的第一个字节是“F”
unsigned short CRC; //校验码
long Size; //数据长度
long Position; //文件指针
char Data[1000]; //数据区
} TSendFileData;
说明:
1、标志:表示这个数据包的类型(详细说明见后)。
2、校验码:一般情况下,校验码放在整个数据包的最后面。这里把它放在这里的原因是由于数据包的长度不定,操作略有不便,所以放到这里。注意在计算校验码时要先把这个字段清零,然后再计算。至于校验码的形式,建议采用CRC校验方式。我这里是CRC16方式。也可以用其它校验方式。
3、数据长度:指明数据区中实际数据的字节数。
4、文件指针:指明本数据区中的数据块在被传文件中的文件指针位置。(这个字段在不同类型的数据包中有不同的意义,也就是在传送一些特殊数据包时,利用这个字段传输一些特殊的数据(详细说明见后)。
5、数据区:要传送的数据块。数据的大小,要考虑所采用的传输方式的误码率和传输效率。在UDP方式下,资料建议在1024以内,所以这里是1000字节。

二、数据包类型:
全部数据包分为发送方数据和接收方数据两大类,分别以FS和FR开头。
1、发送方指令以FS开头。
a)FSName:数据包内容是要发送的文件名和文件长度。
FileFlag=”FSName”,Size=文件名长度,Position=文件长度,Data=文件名。
b)FSFile:数据包的内容是被传送文件的数据块信息。
FileFlag=”FSFile”,Size=数据块长度,Position=对应文件的指针位置。Data=文件数据块,除最后一块的长度可能小于1000外,其余长度都是1000。
c)FSStop:发送方通知接收方,接收方所要求的数据块已经发送完毕。
FileFlag=”FSStop”,Size=0,Position=无效,Data=无效。
d)FSCanc:发送方通知接收方中断传输。(一般是发送方用户干预,中断传输)。
FileFlag=”FSCanc”,Size=0,Position=无效,Data=无效。
e)FSRepa:发送方收到接收方传来的数据有错误,通知接收方重发。
FileFlag=”FSRepa”,Size=0,Position=无效,Data=无效。
2、接收方指令以FR开头。
a)FRReje:接收方拒绝接收文件。
FileFlag=”FRReje”,Size=0,Position=无效,Data=无效。
b)FRRead:通知发送方按照指定的块号发送文件数据块。块号组成一个整型数组,存放在Data数据区。一般情况下,一次可以发送的块号数量=数据区长度/sizeof(int)=1000/4=250个。
FileFlag=”FRRead”,Size=sizeof(int)*所需数据块数量,Position=无效,Data=数据块号数组。
c)FREnd:通知发送方整个文件传送完毕。
FileFlag=”FREnd”,Size=0,Position=无效,Data=无效。
d)FRRepa:接收方收到的数据有错误,通知发送方重发。
FileFlag=”FRRepa”,Size=0,Position=无效,Data=无效。
e)FRErr:接收方建立或写文件出错,通知发送方。
FileFlag=”FRErr”,Size=0,Position=无效,Data=无效。
f)FRCanc:通知发送方收到中断命令。
FileFlag=”FRCanc”,Size=0,Position=无效,Data=无效。

二、通信流程:
1、发送方发出[FSName]命令。
2、接收方如果拒绝接收文件,则发送[FRReje]。否则按照指定的文件名建立文件。按照文件长度计算要分的文件块数量,按块数量建立一个块号数组,用来表示已经接收到的文件块。
3、接收方搜索块号数组中未收到的块号,把它组成一个要发送的块号数据,用[FRRead]命令把这个块号数据发发给发送方。
4、发送方按照块号数据读取文件,并发送每一个数据块[FSFile]。
5、接收方把正确收到的数据块按块号写入文件,并把相应的块号数组元素置成已接收。
6、循环执行4-5。
7、当发送方把块号数据中要求的数据块全部发送完毕后,发出[FSStop]命令,通知接收方指定的块号已经发送完毕。
8、循环执行3-7。
9、如果接收方搜索块号数组中已经没有未接收的数据块,则发送[FREnd]通知发送方文件已经全部传送完毕。
10、如果在传送过程中,发送方要强行中断传送,则发出[FSCanc]命令。接收方中断文件接收,并回应[FRCanc]。
11、如果接收方在建立或写文件中出错,发送[FRErr]通知发送方文件错误。
12、如果收到的数据包(不论是发送方还是接收方)发生校验错误,则用[FSRepa]或[FRRepa]通知对方重发最后一个数据包。
三、几点说明:
1、由于通信过程中不可避免地会出现错误,因此需要对收到的数据包进行校验。如果正确,则通知对方继续发下一个数据包,如果错误,则通知对方重发当前数据包。
2、如果对方在制定的时间内没有返回回应,则说明丢失了数据包,发出数据包的一方应当主动重发最后一个数据包。
3、但是这种一来一往的通信方式,大大降低了通信速度。为了能够尽量提高速度,同时又保证数据的准确完整。对于除[FSFile]以外的命令按照如上这种一来一往的方式来保证数据传送的准确可靠。
4、对整个文件传送过送过程中使用最多的[FSFile]命令,采取不进行应答方式的传送。发送方只管把所需要的数据块连续发出去,而不管接收方是否正确接收。而接收方根据块号数组清除地掌握着还需要重新传送那些块号的数据块。每发一次[FRRead]命令可以包含250个所需块号,而发送方就要发送250个[FSFile]。实践证明,这种方式的文件传送速度很快,而且很可靠。

以上所述只是文件传送程序的主要思路,还可以再扩展比如断点续传、文件下载等功能。希望大家讨论。
...全文
343 74 打赏 收藏 转发到动态 举报
写回复
用AI写文章
74 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuFei 2004-03-22
  • 打赏
  • 举报
回复
up
zhwh 2004-03-16
  • 打赏
  • 举报
回复
照googoler 兄的提议,估计楼主要把tcp内核实现好好看一下了.
zhwh 2004-03-16
  • 打赏
  • 举报
回复
1
kof99th 2004-03-16
  • 打赏
  • 举报
回复
mark一下先
qingenerp 2004-03-09
  • 打赏
  • 举报
回复
收藏
zbl101 2004-03-07
  • 打赏
  • 举报
回复
mark
Tivro 2004-02-28
  • 打赏
  • 举报
回复
mark...


learning....
Jindu 2004-02-25
  • 打赏
  • 举报
回复
这个贴子很有价值!!特别其中所讨论到的这种网络编程思路!!
chenyubang 2004-02-20
  • 打赏
  • 举报
回复
太好了,这正是我要做的东西,

^__________.^ 多谢楼主
勉励前行 2004-01-29
  • 打赏
  • 举报
回复
因極少出錯。沒必要每塊數據包都用CRC校驗。接收完畢後對整個文件做一次CRC,如果出錯,接收方計算每個接收到的“傳送塊”的CRC,發給傳送方,那傳送方做同樣的分塊CRC校驗後應該可以算出要重發哪塊數據。

收藏。
wangxiangsjz 2004-01-29
  • 打赏
  • 举报
回复
楼上提出了一个好方法。
traveler_qt 2004-01-13
  • 打赏
  • 举报
回复
收藏一下
lance 2004-01-09
  • 打赏
  • 举报
回复
up
HHunter 2004-01-07
  • 打赏
  • 举报
回复
关注
wangxiangsjz 2004-01-05
  • 打赏
  • 举报
回复
TCP应该不会出错,UDP会丢包,但会不会出错,我想再测试一下。
wangxiangsjz 2004-01-05
  • 打赏
  • 举报
回复
经过我今天的测试,确实在文件传送过程中,没有发生过CRC校验错误。看来CRC校验是不必要的。
googoler 2004-01-05
  • 打赏
  • 举报
回复
up
pp616 2004-01-04
  • 打赏
  • 举报
回复
那应该是你代码的问题。
mme 2004-01-04
  • 打赏
  • 举报
回复
虽然tcp号称绝对不会出错,但是我觉得还是有些问题的。因为我做过试验,发现tcp也不能绝对保证。
tgame 2004-01-04
  • 打赏
  • 举报
回复
可靠性传输看TCP怎么样实现的就行了,根据实际使用简化就行了。
加载更多回复(54)

1,316

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧