我目前正在处理文件传输程序,我遇到了一个奇怪的问题。 我有两个类:发件人类和收件人类。您可以阅读源代码以及下面的错误消息。 感谢您的帮助。
发信人:
public static void sendFile(final File file, final String ip){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
Socket s = new Socket(ip, 4816);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
DataInputStream dis = new DataInputStream(s.getInputStream());
FileInputStream fis = new FileInputStream(file);
String filename = file.getName();
if(!dis.readUTF().equals("end")){
dos.writeUTF(filename);
dos.flush();
long size = file.length();
byte[] b = new byte[1024];
int read;
dos.writeUTF(Long.toString(size));
dos.flush();
while((read = fis.read(b)) != -1){
dos.write(b, 0, read);
dos.flush();
}
fis.close();
dos.flush();
dos.writeUTF("end");
System.out.println("Sender: Done");
dos.flush();
dis.close();
dos.close();
s.close();
}
return;
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
收件人:
private ServerSocket sock;
private Thread t;
public listener(){
try {
sock = new ServerSocket(4816);
listen();
} catch (IOException e) {
e.printStackTrace();
}
}
private void listen(){
t = new Thread(new Runnable() {
public void run() {
Socket s;
try {
while((s = sock.accept()) != null){
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
String filename = dis.readUTF();
long size = Long.valueOf(dis.readUTF());
byte[] b = new byte[1024];
FileOutputStream fos = new FileOutputStream(new File(filename), true);
long read;
do{
read = dis.read(b, 0, b.length);
fos.write(b, 0, b.length);
}while(!(read < 1024));
System.out.println("Recipient: Done");
fos.close();
dos.close();
dis.close();
s.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.run();
}
错误(传输了1513308160字节中的1086464之后。[1062 * 1024]):
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
at java.io.DataOutputStream.write(Unknown Source)
at main.sender$1.run(sender.java:60)
at java.lang.Thread.run(Unknown Source)
答案 0 :(得分:0)
我认为问题出在接收者身上..
do{
read = dis.read(b, 0, b.length);
fos.write(b, 0, b.length);
}while(!(read < 1024));
您要说的是仅在read
不小于1024时循环。任何read()
操作都可以随时返回小于最大缓冲区长度的值,即使该流不是“at”结束”。特别是涉及网络套接字时。在任何读取时,读取字节的数量可能大于0但小于1024,因为那时只是流可用的字节数。
读取调用会在此时为您提供所有数据(适合缓冲区),而不必阻止。
尝试将其更改为..
int read;
while ((read = dis.read(b, 0, b.length)) != -1 ) {
fos.write(b, 0, read);
}
你在发送者中有这种循环并且它是正确的(虽然你不需要循环中的刷新)。
这种错误比你想象的更常见。多年来我见过很多,甚至在“企业产品”中也是如此。它不会被拾取和修复,因为大部分时间它都有效......直到它没有。
上面的另一个问题是,无论实际上已经将多少字节读入缓冲区,您总是在文件中写入b.length
个字节。