最近被一个朋友问到一个关于sokcet文件传输的问题,他发现他写的代码只能发送一次文件,没办法发送第二次,或者说发送第二次的时候服务端就接收不到了。
部分代码如下
// 开始接收文件
byte[] bytes = new byte[1024];
//byte[] bytes = new byte[dis.available()];
int length = 0;
while((length = dis.read(bytes, 0, bytes.length)) != -1) {
System.out.println(bytes.length);
fos.write(bytes, 0, length);
fos.flush();
}
System.out.println("======== 文件接收成功 [File Name:" + fileName + "] [Size:" + getFormatFileSize(fileLength) + "] ========");
我给他调试的时候发现确确实实发送第一次文件后就就一直阻塞在while循环里了,出不来。本来传输完第一次的文件后应该有打印“======== 文件接收成功 [File。。。。。。”这些信息,但是实际上没有,而且也不报错。调试的时候打断点也是走着走着断点就不见了,要说他是阻塞也不像是阻塞,因为如果是阻塞的话起码断点是会存在的只是无法往下运行了而已,但是他这个调试就是直接断点就消失了,我也懵逼了。后来查资料才发现原来只要客户端的DataOutputStream不close掉,那么服务端的DataInputStream read就永远不等于-1。即使文件的数据已经传完了,DataInputStream依旧会等着客户端DataOutputStream再传数据过来。最后只能通过判断文件的的大小来确认文件是否已经传输完成。
解决代码代码如下
//dis就是DataInputStream
String fileName = dis.readUTF();//文件名字
long fileLength = dis.readLong();//文件长度
File directory = new File(savepath);
if(!directory.exists()) {
directory.mkdir();
}
File file = new File(directory.getAbsolutePath() + File.separatorChar + fileName);
fos = new FileOutputStream(file);
// 开始接收文件
byte[] bytes = new byte[1024];
//byte[] bytes = new byte[dis.available()];
int length = 0;
while((length = dis.read(bytes, 0, bytes.length)) != -1) {
System.out.println(bytes.length);
//fos就是FileOutputStream
fos.write(bytes, 0, length);
fos.flush();
//*************关键的一步**************//
if(fileLength == file.length()) break;
//***************************//
}
System.out.println("======== 文件接收成功 [File Name:" + fileName + "] [Size:" + getFormatFileSize(fileLength) + "] ========");