tcp socket 发送文件,客户端如何判断接收到的是完整的文件?

客户端从socket 读取文件内容,如何知道什么时候读到文件的结尾? 以及接受到读到的文件是否完整?
测试代码发现有时候,接收到的文件是原文件的两倍大小,怎么回事?

阅读 9.8k
3 个回答

看你的Socket是什么类型的socket了,如果是文件的Socket,在Java里,会在文件读完的时候返回 -1, 而一般 TCP Socket就需要会通过上层协议来保证,TCP Socket一般会有复用,所以基本上没有发完这一说,当然你可以选择在发送端发送完文件内容以后主动关闭Socket来表示数据传输完毕,但是这种情况你就没有办法区分出是网络抖动还是发送端真的发完了。

你也可以自己弄一个最简单的协议,在发送真正的文件之前先发送一些别的信息,比如文件长度,文件MD5之类的,当你读到头里指定的字节数之后就可以直接认为已经读完了,比如

文件长度 文件MD5 真实的文件内容
4字节(4GB,根据你最大的文件大小定,保险可以8字节) 16字节 不固定字节数
客户端从socket 读取文件内容,如何知道什么时候读到文件的结尾? 以及接受到读到的文件是否完整?

无法知道。或者说,只有“你”才知道。

你能知道的信息,是收到了多少字节,收到的内容是什么,至于是否“结尾”,是否“结束”,那是你逻辑上的事。

而传输协议如何设计,可以简单去了解一下 HTTP 就明白了。

测试代码发现有时候,接收到的文件是原文件的两倍大小,怎么回事?

你代码有问题。

  1. tcp socket判断数据是否完整的做法是制定合适的应用层协议解决(当然不排除特殊语言将这个协议内置在自己的socket api中),我不考虑这种特殊情况。

2.用到什么技术呢?有限状态机。那么有的同学可能不是很清楚有限状态机是个什么东西,不要紧,是个很简单东西。以这个问题举例,看完就知道了。

  1. 怎么做?很简单,我不是要发文件给对方吗,但是文件可能很大,几百G,也可能很小200B,对吧。不管怎么样,我们都没有办法假设认为发送端一次性往socket里面write能全部写进去,也没有办法认定接收端一次性能read出来。那我们就在发送的时候双方协商一个规则:我要给你发文件,最先会发4个字节(具体多少你自己定),这4个字节是的值就表示接下来这个文件的大小。那问题很好解决啦,发送端先判断即将发送的数据的大小,往socket中write一个4个字节的数,解决一直往socket中写文件,其他不用管,一直写,写完为止。那么接收端发现数据来了,先别管,读出4个字节,然后看这个数字是多大,说明接下来我要持续的读多少个字节,就能组成一个文件。完美解决。假设我连续发3个文件,没关系,接收端都是先读4个字节,假设读出来数据是10G,那么他接着读10G的数据出来,就是这个文件,接着在读4个字节,假设是200B,那么接着在读200B个字节数据出来,就是第二个文件的大小,以此类推。
  2. 上述的方式就是一个简单的状态机。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进