繁体   English   中英

通过套接字发送大文件时出错

[英]Error while sending large files through socket

我正在尝试通过套接字发送大文件。 该程序适用于较小的文件(例如html页面或pdf),但是当我发送超过3/4 mb的文件时,输出始终会损坏(使用文本编辑器查看它时,我注意到最后几行始终会丢失)。

这是服务器的代码:

BufferedInputStream in = null;
    FileOutputStream fout = null;
    try {
        server = new ServerSocket(port);

        sock = server.accept();
        in = new BufferedInputStream(sock.getInputStream());

        setPerc(0);

        received = 0;

        int incByte = -1;
        fout = new FileOutputStream(path+name, true);
        long size = length;
        do{
            int buffSize;
            if(size >= 4096){
                buffSize = 4096;
            }else{
                buffSize = 1;
            }
            byte[] o = new byte[buffSize];
            incByte = in.read(o, 0, buffSize);
            fout.write(o);

            received+=buffSize;
            setPerc(calcPerc(received, length));
            size -= buffSize;
            //d("BYTE LETTI => "+incByte);
        }while(size > 0);
        server.close();
    } catch (IOException e) {
        e("Errore nella ricezione file: "+e);
    }finally{
        try {
            fout.flush();
            fout.close();
            in.close();
        } catch (IOException e) {
            e("ERRORE INCOMINGFILE");
        }
    }
    pr.release(port);

这是客户端的代码:

FileInputStream fin = null;
    BufferedOutputStream out = null;
    try {
        sock = new Socket(host, port);

        fin = new FileInputStream(file);
        out = new BufferedOutputStream(sock.getOutputStream());

        long size = file.length();
        int read = -1;
        do{
            int buffSize = 0;
            if(size >= 4096){
                buffSize = 4096;
            }else{
                buffSize = (int)size;
            }

            byte[] o = new byte[buffSize];
            for(int i = 0; i<o.length;i++){
                o[i] = (byte)0;
            }
            read = fin.read(o, 0, buffSize);
            out.write(o);
            size -= buffSize;
            //d("BYTE LETTI DAL FILE => "+read);
        }while(size > 0);
    } catch (UnknownHostException e) {
    } catch (IOException e) {
        d("ERRORE NELL'INVIO DEL FILE: "+e);
        e.printStackTrace();
    }finally{
        try {
            out.flush();
            out.close();
            fin.close();
        } catch (IOException e) {
            d("Errore nella chiusura dei socket invio");
        }
    }

我认为这与缓冲区大小有关,但我无法弄清这里出了什么问题。

这是不正确的:

        byte[] o = new byte[buffSize];
        incByte = in.read(o, 0, buffSize);
        fout.write(o);

您正在阅读最多 buffSize字节,然后写准确 buffSize字节。

您在另一端也正在做相同的事情。

您可以从文件中读取1时逃脱。但是,当你从一个套接字读那么read容易给你一个部分填充缓冲,特别是如果写到底能不能始终保持阅读的未来最终,因为您正在通过大量传输来锤击网络。

正确的方法是:

        incByte = in.read(o, 0, buffSize);
        fout.write(o, 0, incByte);

1-已经观察到,当您从本地文件readread调用通常会为您提供所请求的所有字节(取决于文件大小等)。 因此,如果将buffSize设置为文件的长度,则从本地文件读取该代码可能会起作用。 但这是一个坏主意,因为您所依赖的行为是Java或典型操作系统无法保证的。

您可能在这里遇到问题。

read = fin.read(o, 0, buffSize);
out.write(o);

在这里, read提供了您实际上刚刚读取的字节数。 在下一行,您应该只写出已读取的字节数。

换句话说,您不能期望正在读取的文件的大小是缓冲区大小的倍数。

同样,请检查您的服务器代码。

在Java中复制流的正确方法如下:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

其中count是一个int, buffer是一个长度大于0(通常为8k)的byte[]数组。 您不需要在循环内分配字节数组,也不需要特定大小的字节数组。 具体地说,分配与文件一样大的缓冲区完全浪费了空间。 它仅适用于Integer.MAX_VALUE字节的文件,并且无法缩放。

您确实需要保存“ read()”返回的计数,并在“ write()”方法中使用它,如上所示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM