再调用socket API进行传输时会涉及到很多细节的问题,其中一条便是文件传输的结尾判定。
这里的文件指广泛的文件而不单字符文件,因此无法使用EOF或者‘ ’来判定文件什么时候结束。
如果不进行恰当的判定,接收方将重复接收最后一个buf里面的内容。直至填满整个文件!
很多人提到了传输文件之前先发送文件长度。这样通过对比该长度与接收到的长度来判定是否继续写入文件。
这是一个比较麻烦,但是很好的机制,特别是对于二进制流传输的文件。
我一开始客户端添加进这一行:
#define MAX 1024
unsigned char buf[MAX];
while((fileBytes = recv(sockfd, buf, sizeof(buf), 0)) && (locallen < filelen)) {//filelen是服务器发送过来的文件长度
if(fileBytes == -1) {
perror("fail to receive datasn");
exit(1);
}
fwrite(buf, sizeof(char), MAX, infp);
locallen += fileBytes;//已接收文件长度
}
可是马上我就发现这段代码并不奏效。或者说不那么奏效,虽然接收到的文件不再肆意膨胀,但是与源文件长度依然有距离。
最终结果表现为以下两点:
1/传输小于1024Bytes的文件时,以545Bytes文本文件为例,会将文件自动用 补齐至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 datasn");
exit(1);
}
diff = filelen - locallen;
if(diff < 0) //应付情况1
fwrite(buf, sizeof(char), filelen, infp);
else if(diff < MAX) { //应付情况2/3
fwrite(buf, sizeof(char), diff, infp);
locallen += diff;
}
else {
fwrite(buf, sizeof(char), fileBytes, infp);
}
locallen += fileBytes;
}
}
最后
以上就是自觉缘分最近收集整理的关于Socket对传输文件结尾的判定的全部内容,更多相关Socket对传输文件结尾内容请搜索靠谱客的其他文章。
发表评论 取消回复