Java Socket 文件上传问题,输入流读取文件阻塞怎么解决?

2020-11-15 15:37:09 +08:00
 industryhive

自己用 java socket 写了一个文件上传下载的小工具,分为服务端和客户端,客户端上传文件,服务端接收文件。但是部署之后,服务端的输入流总是被阻塞,有大佬能看出是什么问题吗?

客户端代码:

public static String upload(String fileName, FileInputStream fis) {
    if (fis == null) {
        System.out.println("FileInputStream Is Null");
        return null;
    }
    Socket storageSocket = null;
    DataOutputStream dos = null;
    DataInputStream dis = null;
    String filePath = null;
    try {
        System.out.println("00000000000");
        RapidMessage contactMsg = Contactor.contact(BaseProtocol.UPLOAD_COMMAND);
        if (contactMsg.getStatus() != 200) {
            System.out.println(contactMsg.getResult());
            return null;
        }
        System.out.println(contactMsg.getResult());
        storageSocket = new Socket(InetAddress.getByName(contactMsg.getResult()), Integer.parseInt(ConfigLoader.STORAGE_PORT));
        dos = new DataOutputStream(storageSocket.getOutputStream());
        dos.write(Contactor.getHeader(BaseProtocol.UPLOAD_COMMAND));
        dos.writeUTF(fileName);
        byte[] fileBytes = new byte[1024];
        System.out.println("11111111111");
        int length;
        while ((length = fis.read(fileBytes)) != -1) {
            System.out.println("------");
            dos.write(fileBytes, 0, length);
        }
        System.out.println("22222222222");
        storageSocket.shutdownOutput();
        dis = new DataInputStream(storageSocket.getInputStream());
        System.out.println("33333333333");
        int status = dis.read();
        System.out.println("44444444444");
        String result = dis.readUTF();
        System.out.println("55555555555");
        if (status != 200) {
            System.out.println(result);
            return null;
        }
        System.out.println("66666666666");
        filePath = result;
        System.out.println("Upload Success: " + filePath);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fis.close();
            if (dis != null) {
                dis.close();
            }
            if (dos != null) {
                dos.close();
            }
            if (storageSocket != null) {
                storageSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return filePath;
}

服务端代码:

public static void upload(Socket connection) {

    System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeeeee");

    DataInputStream dis = null;
    FileOutputStream fos = null;
    try {

        System.out.println("ffffffffffffffffffffffffffff");

        dis = new DataInputStream(connection.getInputStream());

        System.out.println("ggggggggggggggggggggggggggggg");

        String stage_path = Initializer.STORE_PATH + "/" + Initializer.currentStage;
        File stagePath = new File(stage_path);

        System.out.println("hhhhhhhhhhhhhhhhhhhhhhhhhhhhh");

        if (!stagePath.exists()) {
            Logger.error("Path Not Found: " + stage_path);
            Sweeper.close(connection, BaseProtocol.RESPONSE_FAILURE, "Path Not Found: " + stage_path);
            return;
        }
        if (!stagePath.isDirectory()) {
            Logger.error("Path Is Not A Directory: " + stage_path);
            Sweeper.close(connection, BaseProtocol.RESPONSE_FAILURE, "Path Is Not A Directory: " + stage_path);
            return;
        }

        System.out.println("iiiiiiiiiiiiiiiiiiiiiiiiiiiii");

        String storageId = Integer.toHexString(Integer.parseInt(Initializer.STORAGE_ID));

        System.out.println("jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj");

        if (storageId.length() == 1) storageId = "0" + storageId;
        String encoding = "N" + storageId + new Date().getTime() + (int) (Math.random() * 90 + 10);
        byte[] enSrc = encoding.getBytes(StandardCharsets.UTF_8);
        String encoded = Base64.getEncoder().encodeToString(enSrc);

        System.out.println("kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk");

        String realName = dis.readUTF();

        System.out.println("lllllllllllllllllllllllllllllllllll");

        String fileName;
        if (realName.contains(".")) {
            String extension = realName.substring(realName.lastIndexOf("."));
            fileName = encoded + extension;
        } else {
            fileName = encoded;
        }

        System.out.println("mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm");

        File file = new File(stage_path + "/" + fileName);
        fos = new FileOutputStream(file);
        byte[] bytes = new byte[1024];
        int length;

        System.out.println("nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn");

        while ((length = dis.read(bytes)) != -1) {
            fos.write(bytes, 0, length);
        }

        System.out.println("oooooooooooooooooooooooooooooooo");

        String uploadPath = "group" + Initializer.GROUP_ID + "/M00/" + Initializer.currentStage + "/" + fileName;
        Logger.info("Upload File Success: " + uploadPath);

        System.out.println("ppppppppppppppppppppppppppppppppp");

        Sweeper.close(connection, BaseProtocol.RESPONSE_SUCCESS, uploadPath);
        String[] filesNum = stagePath.list();
        if (filesNum != null && filesNum.length > 99) {
            Initializer.stageIndex++;
            Initializer.currentStage = 					   Initializer.STAGE_NAMES[Initializer.stageIndex];
            Initializer.nextStage = Initializer.STAGE_NAMES[Initializer.stageIndex + 1];
        }
        System.out.println("uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fos != null) {
                fos.close();
            }
            if (dis != null) {
                dis.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端代码在输出“kkkkkkkkkkkkkkkkkkkkkkk”之后就不再输出了,又试过几次之后发现,服务端代码有几次也会在输出“nnnnnnnnnnnnnnnnnnnn”之后不再输出。这是什么原因呢?难道 DataInputStream.readUTF()也会阻塞吗?还有难道即使客户端在调用 socket.shutdownoutput()之后,输入端 DataInputStream.read(byte[])仍然会阻塞吗?

1165 次点击
所在节点    Java
2 条回复
laminux29
2020-11-15 20:33:56 +08:00
第一次写复杂的东西,建议先别急着编码,先画流程图。

然后对照流程图,进行编码。

出了问题,按照流程图,对每个环节进行调试,一般情况下,到了这里,问题能自己解决。

如果还解决不了,把流程图和代码一起发出来,并在代码里,注明每段代码,对应的是哪块流程。
zzh7982
2020-11-16 16:12:32 +08:00
客户端 socket.close()之后看看 服务端还阻塞吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/725462

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX