Socket对传输文件结尾的判定

来源:互联网 发布:淘宝秒刷销量一天千单 编辑:程序博客网 时间:2024/04/30 16:10

再调用socket API进行传输时会涉及到很多细节的问题,其中一条便是文件传输的结尾判定。

这里的文件指广泛的文件而不单字符文件,因此无法使用EOF或者‘\0’来判定文件什么时候结束。

如果不进行恰当的判定,接收方将重复接收最后一个buf里面的内容。直至填满整个文件!

很多人提到了传输文件之前先发送文件长度。这样通过对比该长度与接收到的长度来判定是否继续写入文件。

这是一个比较麻烦,但是很好的机制,特别是对于二进制流传输的文件。


我一开始客户端添加进这一行:

#define MAX 1024unsigned char buf[MAX];while((fileBytes = recv(sockfd, buf, sizeof(buf), 0)) && (locallen < filelen)) {//filelen是服务器发送过来的文件长度if(fileBytes == -1) {perror("fail to receive datas\n");exit(1);}fwrite(buf, sizeof(char), MAX, infp);locallen += fileBytes;//已接收文件长度}


可是马上我就发现这段代码并不奏效。或者说不那么奏效,虽然接收到的文件不再肆意膨胀,但是与源文件长度依然有距离。

最终结果表现为以下两点:

1/传输小于1024Bytes的文件时,以545Bytes文本文件为例,会将文件自动用\0补齐至1024Bytes整。

2/传输大文件时,以JPG图片为例,图片上半部分正常,下半部分色块乱码。

可以判断问题依然出在文件结尾部分。分析如下:

情况1,服务器端进行了正确的传送,但是在写入时误将写入长度设为1024Bytes,因此前545bytes正确写入,后面补入不可预知字符。

情况2,由于文件长度很难是1024的整数倍大小,因此当传输到最后部分时剩余大小将小于1024,此时进入情况1

我还不得不说情况3,当你发现文件本身是8.5M而接收到11.7M时,或许会疑惑,按上面分析最多也就多1024Bytes阿,怎么会多出好几M?!事情是这样的,再传输过程中,由于网络环境的不稳定,不是每次都能保证传输1024Bytes,因此中间可能也在未收到1024的情况下写入了1024。


下面给出解决代码:

while((fileBytes = recv(sockfd, buf, sizeof(buf), 0)) && (locallen < filelen)) {if(fileBytes == -1) {perror("fail to receive datas\n");exit(1);}diff = filelen - locallen;if(diff < 0) //应付情况1fwrite(buf, sizeof(char), filelen, infp);else if(diff < MAX) { //应付情况2/3fwrite(buf, sizeof(char), diff, infp);locallen += diff;}else { fwrite(buf, sizeof(char), fileBytes, infp);}locallen += fileBytes;}}

原创粉丝点击