我的代码挂起但是当我调试它时它永远不会挂起

时间:2011-05-23 17:32:22

标签: java client transfer hang

我有一个运行它时SOMETIMES挂起的java代码。它是一个put命令,它通过套接字(以及输入流等文件从服务器到客户端)。有时它可以工作,但有时它没有,我得到一个错误信息。我尝试了所有可能通过调试的路径,我永远不会让它挂起。有没有办法在日食中检查它?

if (sentence.length() > 3 && sentence.substring(0, 3).equals("put")) {

                    File checkFile = new File(dir.getCurrentPath(), sentence.substring(4));
                    if (checkFile.isFile() && checkFile.exists()) {

                        try {
                            outToServer.writeBytes(sentence + "\n");
                            boolean cont = false;
                            String x;
                            while (!cont) {
                                if ((x = inFromServer.readLine()).equals("continue")) {
                                    cont = true;

                                }
                            }
                            String name = sentence.substring(4);
                            copy.copyFile(name);
                            //                          outToServer.writeBytes("continue" + "\n");

这是接收PUT请求的客户端代码(即put test.txt接受文件test.txt并将其放入服务器的本地目录。

复制文件:(复制数据的东西)

File checkFile = new File(dir.getCurrentPath(), file);
    if (checkFile.isFile() && checkFile.exists()) {

        DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream());
        //              byte[] receivedData = new byte[8192];
        File inputFile = new File(dir.getCurrentPath(), file);
        byte[] receivedData = new byte[(int) inputFile.length()];
        //      String theLength = "" + inputFile.length();
        outToClient.writeBytes("" + inputFile.length() + "\n");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(getCopyPath(file)));

        //      if (extension.equals("")) {
        //          extension = "txt";
        //      }
        //          BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //          boolean cont = false;
        //          while (!cont) {
        //              if (inFromClient.readLine().equals("continue")) {
        //                  cont = true;
        //
        //              }
        //          }
        //          outToClient.writeBytes("continue" + "\n");

        bis.read(receivedData, 0, receivedData.length);
        OutputStream os = socket.getOutputStream();
        os.write(receivedData, 0, receivedData.length);
        //          outToClient.writeBytes("finish" + "\n");
        os.flush();

服务器上的协议(复制文件中的内容)

if (get.equals("put")) {
                    //so the client sends: the put request
                    //then sends the length 
                    try {
                        BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream());
                        outToClient.writeBytes("continue" + "\n");
                        int length = Integer.parseInt(inFromClient.readLine());
                        //                      String x = "";
                        //                      boolean cont = false;
                        //                      while (!cont) {
                        //                          String temp = inFromClient.readLine();
                        //                          if (temp.equals("finish")) {
                        //                              cont = true;
                        //                          }
                        //                          else {
                        //                              x += temp;
                        //                          }
                        //                      }
                        byte[] recieveFile = new byte[length];
                        InputStream is = socket.getInputStream();
                        FileOutputStream fos = new FileOutputStream("Copy " + input.substring(4));
                        BufferedOutputStream bos = new BufferedOutputStream(fos);
                        int bytesRead;
                        int current = 0;
                        bytesRead = is.read(recieveFile, 0, recieveFile.length);
                        current = bytesRead;

如果你不能回答具体的问题,请告诉我如何调试挂起的代码或如何调试并发代码。(顺便说一下,传递信号的方式是通过传递令牌,你可以看,即服务器发出一个继续令牌,告诉客户端开始发送数据,我没有通过线程方法通知和等待,因为我无法使用,因为任何单个对象只有1个方法。

2 个答案:

答案 0 :(得分:2)

当您的进程挂起时,获取进程的当前堆栈转储。这将告诉你为什么这个过程被挂起了。

请注意,您的程序中至少有一个错误,因为您没有处理InputStream.read()方法的返回值,这至少会导致您在服务器端丢失数据。 (有关详细信息,请参阅@ rk2010的答案)。

但是,你的主要错误是,当你将BufferedReader包装在套接字InputStream周围时,你可能最终会从流中“窃取”更多的字节而不是正常的长度值。当BufferedReader从底层流中读取数据时,它可以读取比readLine()方法中实际返回的数据更多的数据(因此,它可以在内部读取1000个字符,但第一个“行”可能只包含20个字符)。如果继续使用BufferedReader,一切都很好,但如果丢弃BufferedReader并尝试从底层流中读取更多数据,那么您将获得的数据少于预期。所以,当你去阅读文件内容时,没有足够的字节可用。

相反,您应该独占使用DataOutputStream / DataInputStream。将长度写为长值(即DataOutputStream.writeLong(long)),然后写入后的字节(即DataOutputStream.write(byte[]))。然后使用DataInputStream中的相应方法读取数据。因为您可以在读取时专门使用DataInputStream(首先读取文件大小然后读取实际文件字节),所以在切换读取“模式”时不会有丢失字节的风险(此外,DataInputStream 不 em>执行任何内部缓冲,如BufferedReader)。不要使用读者/作者。

答案 1 :(得分:0)

在每次读写命令后添加日志记录。为每个线程命名。 运行程序,看看日志如何与你期望的一致。

请注意,您不能总是像您一样依赖读取方法。安全的阅读方式是循环,直到你得到一个负长度。

int len = -1;
byte[] buff = new byte[1024]; // for 4KB, use:  4* 1024

while ( (len = is.read(buff, 0, buff.length)) > -1){
  // copy len number of bytes from buff array into some other place.
}

查看IOUtils.copy方法 from Apache Commons IOUtils class