传输一定量的字节后文件传输停止

时间:2017-01-30 23:21:05

标签: java networking

我目前正在处理文件传输程序,我遇到了一个奇怪的问题。 我有两个类:发件人类和收件人类。您可以阅读源代码以及下面的错误消息。 感谢您的帮助。

发信人:

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)

1 个答案:

答案 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个字节。