V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
industryhive
V2EX  ›  Java

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

  •  
  •   industryhive · 2020-11-15 15:37:09 +08:00 · 1172 次点击
    这是一个创建于 1478 天前的主题,其中的信息可能已经有所发展或是发生改变。

    自己用 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[])仍然会阻塞吗?

    2 条回复    2020-11-16 16:12:32 +08:00
    laminux29
        1
    laminux29  
       2020-11-15 20:33:56 +08:00
    第一次写复杂的东西,建议先别急着编码,先画流程图。

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

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

    如果还解决不了,把流程图和代码一起发出来,并在代码里,注明每段代码,对应的是哪块流程。
    zzh7982
        2
    zzh7982  
       2020-11-16 16:12:32 +08:00
    客户端 socket.close()之后看看 服务端还阻塞吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3281 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 13:02 · PVG 21:02 · LAX 05:02 · JFK 08:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.