0

在我的客戶端服務器應用程序中,它能夠接收命令並返回結果。當我嘗試從服務器端下載文件時發生此問題。進入下載命令後,服務器提示顯示了這個錯誤,如何以適當的方式關閉OutputStream?

java.net.SocketException: socket closed 

圖片:

Image

否則編程工作正常,也是它能夠將文件下載到客戶端。

注意我可能的原因是關於outputSteram的關閉(在我的ServerSide項目中),這可能沒有以正確的方式完成。

我的完整的工作代碼:

服務器端:

public class ServerSide { 

    private BufferedReader inputFromClient; 
    private PrintWriter outputToClient; 
    private FileInputStream fis; 
    private OutputStream os; 
    private static final int PORT = 8000; 
    private ServerSocket serverSocket; 
    private Socket socket; 

    public static void main(String[] args) { 
     int port = PORT; 
     if (args.length == 1) { 
      port = Integer.parseInt(args[0]); 
     } 
     new ServerSide(port); 
    } 

    private boolean fileExists(File[] files, String filename) { 
     boolean exists = false; 
     for (File file : files) { 
      if (filename.equals(file.getName())) { 
       exists = true; 
      } 
     } 
     return exists; 
    } 

    public ServerSide(int port) { 
     // create a server socket 
     try { 
      serverSocket = new ServerSocket(port); 
     } catch (IOException ex) { 
      System.out.println("Error in server socket creation."); 
      System.exit(1); 
     } 

     while (true) { 
      try { 

       socket = serverSocket.accept(); 
       outputToClient = new PrintWriter(socket.getOutputStream()); 
       inputFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

       while (true) { 

        String request = inputFromClient.readLine(); 

        if (!request.startsWith("exit") && !request.startsWith("pwd") && !request.startsWith("list") && !request.startsWith("GET")) { 
         outputToClient.println("Wrong request\r\n" 
           + "\r\n"); 
        } else if (request.startsWith("exit")) { 
         break; 
        } else if (request.startsWith("pwd")) { 
         File file = new File(System.getProperty("user.dir")); 
         outputToClient.print("Status OK\r\n" 
           + "Lines 1\r\n" 
           + "\r\n" 
           + "Working dir: " + file.getName() + "\r\n"); 
        } else if (request.startsWith("list")) { 
         File file = new File(System.getProperty("user.dir")); 
         File[] files = file.listFiles(); 
         outputToClient.print("Status OK\r\n" 
           + "Files " + files.length + "\r\n" 
           + "\r\n" 
           + Arrays.toString(files).substring(1, Arrays.toString(files).length() - 1) + "\r\n"); 
        } else if (request.startsWith("GET")) { 
         String filename = request.substring(4); 
         File file = new File(System.getProperty("user.dir")); 
         File[] files = file.listFiles(); 

         if (fileExists(files, filename)) { 
          file = new File(filename); 
          int fileSize = (int) file.length(); 

          outputToClient.printf("Status OK\r\nSize %d Bytes\r\n\r\nFile %s Download was successfully\r\n", 
            fileSize, filename); 
          outputToClient.flush(); 

          try (FileInputStream fis = new FileInputStream(file)) { 
           os = socket.getOutputStream(); 
           byte[] buffer = new byte[(1 << 7) - 1]; 
           int bytesRead = 0; 

           while ((bytesRead = fis.read(buffer)) != -1) { 
            os.write(buffer, 0, bytesRead); 
           } 

          } 
          os.close();//the problem probably occurs here. 
          // fis.close(); 
         } else { 
          outputToClient.print("Status 400\r\n" 
            + "File " + filename + " not found\r\n" 
            + "\r\n"); 
          outputToClient.flush(); 
         } 
        } 
        outputToClient.flush(); 
       } 
      } catch (IOException e) { 
       System.err.println(e); 
      } 

     } 
    } 
} 

客戶方:

public class ClientSide { 

    private static Socket socket; 
    private static PrintWriter outputToServer; 
    private static BufferedReader inputFromServer; 
    private static InputStream is; 
    private static FileOutputStream fos; 
    private static final int PORT = 8000; 
    private static final String SERVER = "85.197.159.45"; 
    boolean Connected; 
    DataInputStream serverInput; 

    public static void main(String[] args) throws InterruptedException { 
     String server = "localhost"; 
     int port = PORT; 

     if (args.length >= 1) { 
      server = args[0]; 
     } 
     if (args.length >= 2) { 
      port = Integer.parseInt(args[1]); 
     } 

     new ClientSide(server, port); 
    } 

    public ClientSide(String server, int port) { 

     try { 
      socket = new Socket(server, port); 
      serverInput = new DataInputStream(socket.getInputStream()); 
      outputToServer = new PrintWriter(socket.getOutputStream(), true); 
      inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      System.out.println("Client is connected! "); 
      Connected = true; 
      String line = null; 

      Scanner sc = new Scanner(System.in); 
      System.out.print("Type command: "); 

      while (sc.hasNextLine()) { 
       String request = sc.nextLine(); 

       if (request.startsWith("exit")) { 
        outputToServer.println(request); 
        System.out.println("Application exited!"); 
        //outputToServer.flush(); 
        break; 
       } else if (request.startsWith("pwd")) { 
        outputToServer.println(request); 
        outputToServer.flush(); 
       } else if (request.startsWith("list")) { 
        outputToServer.println(request); 
        outputToServer.flush(); 
       } else if (request.startsWith("GET")) { 
        System.out.print("\r\n"); 
        outputToServer.println(request); 
        outputToServer.flush(); 
       } 
       while (Connected) { 
        line = inputFromServer.readLine(); 
        System.out.println(line); 
        if (line.isEmpty()) { 
         Connected = false; 
         if (inputFromServer.ready()) { 
          System.out.println(inputFromServer.readLine()); 
         } 
        } 
        if (line.startsWith("Status 400")) { 
         while (!(line = inputFromServer.readLine()).isEmpty()) { 
          System.out.println(line); 
         } 
         break; 
        } 
        if (request.startsWith("GET")) { 
         File file = new File(request.substring(4)); 
         is = socket.getInputStream(); 
         fos = new FileOutputStream(file); 

         byte[] buffer = new byte[socket.getReceiveBufferSize()]; 
         serverInput = new DataInputStream(socket.getInputStream()); 
         //int bytesReceived = 0; 
         byte[] inputByte = new byte[4000]; 

         int length; 
         while ((length = serverInput.read(inputByte, 0, inputByte.length)) > 0) { 
          fos.write(inputByte, 0, length); 

         } 

         /* 
         while ((bytesReceived = is.read(buffer)) >=0) { 
         //while ((bytesReceived = is.read(buffer))>=buffer) { 
         fos.write(buffer, 0, bytesReceived); 
         } 
         */ 
         request = ""; 
         fos.close(); 
         is.close(); 
        } 
       } 
       System.out.print("\nType command: "); 
       Connected = true; 
      } 
      outputToServer.close(); 
      inputFromServer.close(); 
      socket.close(); 
     } catch (IOException e) { 
      System.err.println(e); 
     } 

    } 
} 

回答

1

問題結束後,我想,是在該命令處理之後(GET )您正在關閉服務器套接字中的那個os.close()調用。意識到osoutputToClientinputFromClient取決於相同的服務器套接字。因此,在關閉os時,您正在影響其他兩個流。然後,在服務GET請求之後,服務器循環會開始並嘗試運行inputFromClient.readLine(),但底層套接字已關閉。

+0

謝謝。我嘗試過不同的方式來解決它。因此我需要知道如何在編碼中實現它。 – Munira

+0

我看到你在發送GET時也在客戶端代碼中運行is.close()。我的建議是:在客戶端註釋該行,並在服務器中使用os.close()。 –

0

服務器被寫入插座,完成後其關閉套接字客戶端收到有機會完成下載/讀取它。您可以改爲使其一旦完成讀取/下載,就會向服務器發送消息以關閉套接字。

+0

阿修羅,謝謝,但我其實已經研究了這麼多關於這個問題的理論解釋。我應用了這些,並沒有奏效。請你具體說明一下,在我的編碼中如何實現? – Munira

0

try-with-resources語句是聲明一個或多個資源的try語句。資源是程序結束後必須關閉的對象。 try-with-resources語句確保每個資源在語句結束時都關閉。任何實現java.lang.AutoCloseable的對象(包含所有實現java.io.Closeable的對象)都可以用作資源。

try(DataOutputStream out= new DataOutputStream(newFileOutputStream("data"))) 
{ 
     out.writeInt(666); 
} 

或者,你可以利用的finally塊來關閉流你使用它

try 
{ 
    DataOutputStream out= new DataOutputStream(newFileOutputStream("data"); 
    out.writeInt(666); 
} 
catch(Exception e) 
{ 
    e.printStackTrace(); 
} 
finally 
{ 
    if(out != null) 
    { 
     out.close(); 
    } 
} 
+0

艾倫,謝謝。但是,你可以看到我有兩個「嘗試」塊。 Ater哪個try-catch塊我需要添加「finally」塊。 – Munira

相關問題