java 通过套接字发送文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6099636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:19:44  来源:igfitidea点击:

Sending files through sockets

javasocketsnetworking

提问by Giannis

Hello there im trying to send files using client-server classes in java. For some reason when the method that sends the file is called the socket closes. here is the code :

您好,我正在尝试使用 Java 中的客户端-服务器类发送文件。出于某种原因,当调用发送文件的方法时,套接字关闭。这是代码:

FileInputStream fIn = new FileInputStream(file);
out = new BufferedOutputStream(clientSocket.getOutputStream());
byte fileContent[] = new byte[(int) file.length()];
fIn.read(fileContent);
for (byte b : fileContent) {
    out.write(b);
}

and the code from the client :

和来自客户端的代码:

FileOutputStream fIn = new FileOutputStream("testing");
BufferedInputStream inAout = new BufferedInputStream(clientSocket.getInputStream());
byte fileContent[] = new byte[1000000];
inAout.read(fileContent);
fIn.write(fileContent);

and the error message i get : SEVERE: null java.net.SocketException: Socket closed

以及我收到的错误消息:SEVERE: null java.net.SocketException: Socket closed

Im not really experienced with this so if any can help it would be great.

我在这方面并没有真正的经验,所以如果有任何帮助,那就太好了。

回答by WhiteFang34

The InputStream.read(byte[])method returns an intfor the number of bytes it actually read. It's not guaranteed to read as many bytes as you requested from the byte array. It'll often return the size of the underlying buffer and you'll have to call it many times.

InputStream.read(byte[])方法返回int它实际读取的字节数。不能保证读取的字节数与您从字节数组中请求的一样多。它通常会返回底层缓冲区的大小,您将不得不多次调用它。

You can use this to be more efficient by streaming the bytes from the socket to the file instead of buffering the whole byte array in memory. Likewise on the server side you can do the same thing to save memory and be faster than writing a byte at a time.

您可以通过将字节从套接字流式传输到文件而不是在内存中缓冲整个字节数组来提高效率。同样在服务器端,你可以做同样的事情来节省内存并且比一次写入一个字节更快。

Here's a working example of a server and client in one that connects to itself to transfer a file:

这是一个服务器和客户端连接到自身以传输文件的工作示例:

public class SocketFileExample {
    static void server() throws IOException {
        ServerSocket ss = new ServerSocket(3434);
        Socket socket = ss.accept();
        InputStream in = new FileInputStream("send.jpg");
        OutputStream out = socket.getOutputStream();
        copy(in, out);
        out.close();
        in.close();
    }

    static void client() throws IOException {
        Socket socket = new Socket("localhost", 3434);
        InputStream in = socket.getInputStream();
        OutputStream out = new FileOutputStream("recv.jpg");
        copy(in, out);
        out.close();
        in.close();
    }

    static void copy(InputStream in, OutputStream out) throws IOException {
        byte[] buf = new byte[8192];
        int len = 0;
        while ((len = in.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
    }

    public static void main(String[] args) throws IOException {
        new Thread() {
            public void run() {
                try {
                    server();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        client();
    }
}

回答by Aaron Digulla

The reason is pretty simple: The call inAout.read(fileContent)will return after about 4KB of data has been transmitted. That's the input buffer size. So instead of a single huge read, you need a loop and many reads and write as many bytes to fInas you got from the socket.

原因很简单:inAout.read(fileContent)在传输了大约 4KB 的数据后,调用将返回。那是输入缓冲区大小。因此,您需要一个循环和多次读取并写入与fIn从套接字获得的字节数一样多的字节,而不是一次巨大的读取。

Also don't forget to flush the output on the server side (closing will flush it) or some data will be lost.

另外不要忘记刷新服务器端的输出(关闭将刷新它)否则一些数据将丢失。

回答by user207421

SEVERE: null java.net.SocketException: Socket closed

That means you've closed the socket yourself and then called another operation that needs it open. For example, closing the socket or its input stream or output stream closes the other stream and the socket. Somewhere or other you are doing that.

这意味着您自己关闭了套接字,然后调用了另一个需要打开它的操作。例如,关闭套接字或其输入流或输出流将关闭另一个流和套接字。某处或其他地方你正在这样做。