我正在开发一个客户端和服务器之间的简单文件传输应用程序。 这是我的代码: 我的客户(发件人):
try{
File file_sender=XMLParser.register(peername, address, port, listfile);
int count;
byte[] buffer = new byte[1024];
int len=(int) file_sender.length();
byte[] mybytearray = new byte[len];
DataOutputStream output=new DataOutputStream(Info.connection.getOutputStream());
output.writeInt(len);
System.out.println(len);
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file_sender));
bis.read(mybytearray, 0, len);
output.write(mybytearray, 0, len);
bis.close();
output.close();
// Info.connection.close();
}catch(Exception ex){
System.out.println(ex.toString());
}
我的服务器(接收方):
public class IOThread extends Thread {
private Socket connection;
private DataInputStream input;
public IOThread(Socket connection) throws IOException{
this.connection=connection;
input=new DataInputStream(connection.getInputStream());
}
@Override
public void run(){
while(true){
try{
int filesize=12022386;
int bytesRead;
int currentTot = 0;
byte[] bytearray = new byte [filesize];
int len=input.readInt();
FileOutputStream fos = new FileOutputStream("data.xml");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead=input.read(bytearray, 0,bytearray.length);
System.out.println(len);
currentTot=bytesRead;
do{
bytesRead=input.read(bytearray, currentTot, (bytearray.length-currentTot));
if(bytesRead>=0) currentTot+=bytesRead;
System.out.println("pos: "+currentTot);
} while(len!=currentTot);
bos.write(bytearray, 0, currentTot);
bos.close();
//connection.close();
System.out.println("Done");
}catch(EOFException ex){
System.out.println(ex.toString());
break;
}catch( Exception ex){}
}
}
我想传输多个文件,所以我不想关闭套接字。因此,我使用变量“len”来检查文件是否完全转移。
如果我在发送文件后关闭“输出”,那么服务器会抛出EOFException并且文件发送成功。
当我不关闭输出时,服务器无法接收文件成功。但是Server不会抛出EOFException。
你可以帮我解决这个问题吗? 更新:如果我没有在客户端关闭变量“output”,那么这是我在控制台屏幕上的输出:246
pos:496
感谢。 抱歉我的英语不好
答案 0 :(得分:2)
两件事:
首先,您似乎忽略了接收代码中的文件长度?你有:
int filesize=12022386;
int bytesRead;
int currentTot = 0;
byte[] bytearray = new byte [filesize];
int len=input.readInt();
无论len
的值是什么,您都在调整bytearray的大小为12022386字节,并且您要求输入流中的那么多字节。
其次,当您关闭输出流时,任何尚未写入的缓存/缓冲数据都会自动刷新(例如,在您的情况下,发送到服务器)。
当您完成发送第一个文件以强制它完成将所有数据发送到服务器时,显式刷新输出流。然后,您可以继续将该输出流用于其他事项。
传输完成后,在发送代码中执行output.flush()
。
答案 1 :(得分:2)
问题是你读取的文件超出了文件大小,即不是读取len
个字节,而是读取bytearray.length
个字节,这个字节更大。
因此,您阅读的时间超过len
字节,因此永远不会满足len!=currentTot
,因为您可以从示例输出中看到currentTot == 496
和len == 246
。< / p>
在while循环中进行以下更改:
do{
bytesRead=input.read(bytearray, currentTot, (len - currentTot));
if(bytesRead>=0) currentTot += bytesRead;
System.out.println("pos: " + currentTot);
} while(len != currentTot);
为了确保您不会因为类似错误而无休止地循环,您可以使用currentTot < len
代替len != currentTot
作为您的条件。
此外,由于您已经在使用DataInputStream
,请考虑使用readFully
读取套接字内容。这将阻塞,直到从套接字读取给定数量的字节,从根本上消除了对while循环的需要。阅读更多here。
答案 2 :(得分:2)
抛弃所有循环并在发送文件后使用DataInputStream.readFully();
关闭套接字;不要结束文件长度;并使用正常大小的缓冲区,比如说8192字节。
答案 3 :(得分:0)
您的BufferedOutputStream
填充似乎不正确。下面的代码必须在while循环中。
bos.write(bytearray, 0, currentTot);
尝试这样的事情:
BufferedOutputStream buffOut=new BufferedOutputStream(fos);
byte []arr = new byte [1024 * 1024];
int available = -1;
while((available = buffIn.read(arr)) != -1) {
buffOut.write(arr, 0, available);
}
buffOut.flush();
buffOut.close();
再次测试。
编辑:用@Jason的正确评论更新了我的答案。