套接字发送的文件大小为 0 并且访问被阻止,除非我使用 System.exit(0),如何避免这种情况?

Posted

技术标签:

【中文标题】套接字发送的文件大小为 0 并且访问被阻止,除非我使用 System.exit(0),如何避免这种情况?【英文标题】:file size sent by socket is 0 and access blocked unless I use System.exit(0), how to avoid this? 【发布时间】:2014-01-24 15:57:44 【问题描述】:

我有一个 android 平板电脑客户端,它在它和一个在 Windows 7 上运行的 Java 服务器之间发送和接收一些文件。除了一个奇怪的问题外,一切都很完美。其中一个文件,在本例中,从客户端 android 平板电脑收到的 transfer.pdf 无法打开并显示大小为 0。当我尝试打开此文件时,我从 adobe reader 收到错误消息“此文件是已打开或正在被其他应用程序使用。”

解决这个问题的唯一方法是使用 System.exit(0) 来杀死整个应用程序,如果我这样做,文件会显示正确的大小并且可以毫无问题地打开。但是我宁愿不使用 System.exit(0)。我已经尝试了一切,但没有其他任何工作。

finally块用于关闭所有socket输入输出,关闭后我将文件变量和socket设置为null。

有其他人遇到过这个问题吗?如何在不使用 System.exit(0) 的情况下完成这项工作?

服务器代码

public class MultiThreader implements Runnable 
Socket socket;
File fileDirectory;
File file;
public int fileSizeFromClient;
FileOutputStream fos = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
DataInputStream dis = null;
DataOutputStream dos = null;
long length;

public MultiThreader(Socket socket)
    System.out.println("print out from multithreader class");
    this.socket = socket;

 // multiThreader

@Override
public void run() 

    System.out.println("multi threader started");

      //================================================================================================
    //==== action #1 read in transfer.pdf file from client ===========================================

    int bufferSize = 0;

    try 

     bis = new BufferedInputStream(socket.getInputStream());
     dis = new DataInputStream(bis);

     fileSizeFromClient = dis.readInt();
     System.out.println("file size for transfer.pdf from client is " + fileSizeFromClient);

      fileDirectory = new File("C:/DOWNLOAD/");
        if (!fileDirectory.exists()) 
            fileDirectory.mkdir();
      
     file = new File("C:/DOWNLOAD/transfer.pdf");
      file.createNewFile();

       fos = new FileOutputStream(file);
       bos = new BufferedOutputStream(fos);
       dos = new DataOutputStream(bos);

       byte[] buffer = new byte[fileSizeFromClient];

      int totalBytesRead = 0;

        while(totalBytesRead < fileSizeFromClient)
            int bytesRemaining = fileSizeFromClient - totalBytesRead;
            int bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, bytesRemaining));
            if(bytesRead == -1) 
                break;
             else 
                dos.write(buffer, 0, bytesRead); 
                    totalBytesRead += bytesRead;
            
         // while

       // ===================================================================================================== 
       // === action #2 send transfer2.pdf file to client =====================================================

      file = new File("C:/DOWNLOAD/transfer2.pdf");
      file.createNewFile();

      fis = new FileInputStream(file);
      bis = new BufferedInputStream(fis);
      dis = new DataInputStream(bis);
      bos = new BufferedOutputStream(socket.getOutputStream());
      dos = new DataOutputStream(bos);

      length = file.length();

       System.out.println("file size for transfer2.pdf sent to client is " + length);

      dos.writeInt((int) length);

      int count = 0;

      buffer = new byte[(int)length];

      while((count = bis.read(buffer)) > 0)
          bos.write(buffer, 0, count);
      

           //=====================================================================================
      //=== action #3 read in transferImage.jpg from client =================================

     bufferSize = 0;

     bis = new BufferedInputStream(socket.getInputStream());
     dis = new DataInputStream(bis);

     fileSizeFromClient = dis.readInt();
     System.out.println("file size for transferImage.jpg from client is " + fileSizeFromClient);

      file = new File("C:/DOWNLOAD/transferImage.jpg");
      file.createNewFile();

       fos = new FileOutputStream(file);
       bos = new BufferedOutputStream(fos);
       dos = new DataOutputStream(bos);

       buffer = new byte[fileSizeFromClient];

       totalBytesRead = 0;

        while(totalBytesRead < fileSizeFromClient)
            int bytesRemaining = fileSizeFromClient - totalBytesRead;
            int bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, bytesRemaining));
            if(bytesRead == -1) 
                break;
             else 
                dos.write(buffer, 0, bytesRead); 
                    totalBytesRead += bytesRead;
            
         // while

            //=====================================================================================

       catch (IOException ex) 
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
        finally 

                        try 

                                   bis.close();
                                    fis.close();
                                    dis.close();
                                    fos.flush();
                                    fos.close();
                                    bos.flush();
                                    bos.close();
                                    dos.flush();
                                    dos.close();
                                    socket.close();
                                    file = null;
                                    fileDirectory = null;
                                   // System.exit(0);

                         catch (IOException e) 
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        

        


  // run

   // MultiThreader

 public class Server 
 ServerSocket serverSocket;
 Socket socket;
 boolean runner = true;

 Server() throws IOException

    serverRunner();
    System.out.println("server constructor started");

  // Server constructor

 public void serverRunner() throws IOException 

    System.out.println("serverrunner started");

     try 

      serverSocket = new ServerSocket(6789, 100);

      runner = true;

        while (runner) 

            socket = serverSocket.accept();

            MultiThreader multi = new MultiThreader(socket);
            Thread t = new Thread(multi);
            t.start();

          // while runner
        catch (IOException ex) 

    

  // serverRunner  

  // class Server

【问题讨论】:

为什么要在 BufferedOutputStream 之上构建缓冲区? 最好不要这样做吗? 毫无意义; BufferedOutputStream 已经在缓冲了……一次只写一个字节,让它处理它。 @ElliottFrisch 但他不是一次读取一个字节。他有一个字节数组,所以他应该调用write(byte[], int, int). 我同意在这种情况下它不必是BufferedOutputStream,但是一次写入一个字节到任何东西都不是一个好主意。 我删除了所有的 bufferedOutputSteams 和 bufferedInputStreams,它的工作原理是一样的。所以我想如果我不需要缓冲流,我将来不会使用它们 【参考方案1】:

不要使用多个流。创建一组流并在套接字的整个生命周期中使用它们。目前,当您用新的BufferedInputStream 替换旧的BufferedInputStream 时,您会丢失数据。

注意:

    您不需要整个文件大小的缓冲区。 8192 可以。您的代码仍然适用于任何大于零的缓冲区大小。 你不需要在new FileOutputStream().之前调用File.createNewFile(),这完全是多余的。

【讨论】:

以上是关于套接字发送的文件大小为 0 并且访问被阻止,除非我使用 System.exit(0),如何避免这种情况?的主要内容,如果未能解决你的问题,请参考以下文章

NSOutputStream 发送旧值 - Objective C

为啥套接字被阻止接收,而我睡在另一个线程上?

循环阻止异步请求被发送。为什么以及如何解决?

IIS 服务器阻止访问 .webp 文件

socket 错误之:OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。

使用 C 中的套接字通过 TCP 发送音频文件