【问题标题】:How to receive and store file using sockets如何使用套接字接收和存储文件
【发布时间】:2017-07-12 11:31:55
【问题描述】:

我正在尝试使用 Sockets 发送文件,但是当我收到文件时,我无法存储它。 调试器显示,代码停在

字节读取 = is.read(mybytearray, current, (mybytearray.length - current));

然后什么也没有发生。

bytesRead = is.read(mybytearray, 0, mybytearray.length); - 等于 17

public static void main(String[] args) throws IOException {
            FileOutputStream fileOutputStream = null;
            BufferedOutputStream bufferedOutputStream = null;
            Socket socket = null;
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(SOCKET_PORT);
                while (true) {
                    System.out.println("Waiting...");
                    try {
                        socket = serverSocket.accept();
                        System.out.println("Accepted connection : " + socket);
                        int bytesRead;
                        int current = 0;
                        byte[] mybytearray = new byte[FILE_SIZE];
                        InputStream is = socket.getInputStream();
                        fileOutputStream = new FileOutputStream(FILE_TO_RECEIVED);
                        bufferedOutputStream = new BufferedOutputStream(bufferedOutputStream);
                        bytesRead = is.read(mybytearray, 0, mybytearray.length);
                        current = bytesRead;

                        do {
                            bytesRead =
                                    is.read(mybytearray, current, (mybytearray.length - current));
                            if (bytesRead >= 0) current += bytesRead;
                        } while (bytesRead > -1);

                        bufferedOutputStream.write(mybytearray, 0, current);
                        bufferedOutputStream.flush();
                        System.out.println("File " + FILE_TO_RECEIVED
                                + " recieved (" + current + " bytes read)");


                    } finally {
                        if (fileOutputStream != null) fileOutputStream.close();
                        if (bufferedOutputStream != null) bufferedOutputStream.close();
                        if (socket != null) socket.close();
                    }
                }
            } finally {
                if (serverSocket != null) serverSocket.close();
            }
        }

【问题讨论】:

    标签: java sockets


    【解决方案1】:

    您可以尝试直接写入 OutputStream,例如将您的 while 循环更改为

    while ((bytesRead = in.read(mybytearray)) > 0) {
        fileOutputStream.write(mybytearray, 0, bytesRead);
    }
    

    根据 Rookie 回答中的描述 - https://stackoverflow.com/a/9548429/2826895

    【讨论】:

    • 没有读取字节时停止可能是连接速度非常慢的问题
    • @ThijsSteel:读取永远不会返回零,除非它被要求读取零字节,无论连接有多慢。
    【解决方案2】:

    由于您有一个名为 FILE_SIZE 的变量,我假设您知道文件的大小。

    不要从流中读取直到您停止获取数据:while (bytesRead > -1),您可能想尝试在您不期望更多数据时停止:while (bytesRead > -1 && current<FILE_SIZE)

    如果您并不总是知道文件的大小,那么您还需要通过套接字传达该大小。这可能只是一个表示文件大小的整数,但也可能类似于 HTTP 中使用的分块编码。

    【讨论】:

    • 这可行,但我写了一个稍微不同的答案。
    【解决方案3】:

    问题出在这两行,正如用户 Thijs Steel 所暗示的那样:

    bytesRead = is.read(mybytearray, current, (mybytearray.length - current));
    if (bytesRead >= 0) current += bytesRead;
    

    读完最后一个字节后,current 变为等于mybytearray.length(假设 FILE_SIZE 确实是以字节为单位的文件大小)。从那时起,您就有了一个无限循环,请求读取零字节,读取尽职尽责并返回零。

    将您的循环停止条件设置为在接收到文件结束 (EOF) 时或在读取 FILE_SIZE 字节后,但不能同时为两者。

    要将 EOF 用作停止条件,您的读取循环需要修改为在读取中使用固定长度的字节缓冲区。使用 FILE_SIZE 作为停止条件要简单得多。您只需将输入流包装在 DataInputStream 中并使用 readFully() 方法,如

    DataInputStream dis =  new DataInputStream(is);
    dis.readFully(mybytearray);
    

    【讨论】:

    • 为什么不两者兼而有之?如果循环停止条件是 EOF(我们现在拥有的),我们将得到无限循环。如果循环停止条件是读取 FILE_SIZE 个字节,则在网络条件下将无法停止
    • @ThijsSteel:我需要澄清我的答案
    • 我认为FILE_SIZE 是一个常数。代码中的任何地方都没有提到它,从大小写可以假设它是一个常数。
    猜你喜欢
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 2014-07-31
    • 2013-11-13
    • 2016-10-06
    • 1970-01-01
    相关资源
    最近更新 更多