2012-04-01 259 views
2

我在編寫客戶端服務器應用程序。我想知道結束連接,哪一方應該決定結束它,客戶端還是服務器?客戶端連接或服務器端?

然後,如果例如客戶端做到了,服務器是否應該保持打開狀態?

假設我們對每個客戶端和服務器下面的代碼:

  socket = new Socket("127.0.0.1",3000); 
........ 

      socket.close(); 

  serverSocket = new ServerSocket(3000); 
      socket = serverSocket.accept(); 
...... 

      serverSocket.close(); 

編輯: 根據馬特的答案,我鍋中我的代碼在這裏,讓看看爲什麼我的代碼不工作:

一般來說,我有一個Jframe程序作爲客戶端,它將連接到一臺服務器,當它打開,我想連接是活着的,因爲它se向服務器和服務器發送信息應該對結果做出響應。但如果我不使用從服務器關閉套接字它提供了一個錯誤,如果我使用,一旦計算之後,關閉連接:

服務器

 private static PrintWriter toClient; 
     private static BufferedReader fromClient; 


    public static void run() throws IOException, SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException, SAXException, XPathExpressionException 
     { 


     System.out.println("Server is waiting for connections..."); 

     while(true) 
     { 
       openStreams(); 
        processClient(); 
        closeStreams(); 
} 

    } 

的OpenStream:

public static void openStreams() throws IOException, SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException, SAXException, XPathExpressionException 
      { 
      serverSocket = new ServerSocket(3000); 
      socket = serverSocket.accept(); 
       System.out.println("Connected"); 

      toClient = new PrintWriter(socket.getOutputStream(),true); 

      fromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); 


      } 

Closestearms :

public static void closeStreams() throws IOException 
      { 
      fromClient.close(); 
      toClient.close(); 
      socket.close(); 
      serverSocket.close(); 
       System.out.println("Disconnected"); 
     } 

我收到的錯誤如果我刪除了closestream();

at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:359) 
    at java.net.ServerSocket.bind(ServerSocket.java:319) 
    at java.net.ServerSocket.<init>(ServerSocket.java:185) 
    at java.net.ServerSocket.<init>(ServerSocket.java:97) 

回答

1

取決於您的應用程序的邏輯。兩者都是有效的,你必須確保你的代碼在兩種情況下都是正確的,因爲如果連接被「非自願」中斷(如網絡丟失),它將在雙方看起來好像另一方關閉了連接。

因此,您的代碼必須優雅地處理這兩種情況。

您的結束代碼是可疑的:您關閉了監聽套接字,這是不尋常的。只有當您不需要更多傳入連接時(即通常在服務器上關閉服務器時),才應關閉監聽套接字。
只關閉您從accept獲得的套接字以結束「對話」,並且不要重新打開服務器偵聽套接字。 (你得到的例外可能在這種情況下是一個「地址已在使用」見How to set reuse address option for a datagram socket in java code?對於如何避免特定問題的例子。)

+0

但林困惑,因爲如果客戶端,然後服務器應該做的** ** socket.close與否?反之亦然 – lonesome 2012-04-01 10:47:33

+0

一旦插座已經在一側封閉,另將獲得異常,如果它試圖在其上運行需要連接到開放的方法。無論它是服務器還是客戶端都無關緊要;一旦連接打開,從TCP的角度來看,兩者都是相同的。 – Mat 2012-04-01 10:52:23

+0

如何閱讀我的編輯?謝謝 – lonesome 2012-04-01 11:05:54

0

任何一方都可以關閉連接 - 既不是「更正確」。

但是,清除代碼中的一個(似乎)誤解很重要:關閉ServerSocket不關閉代表兩個端點之間連接的套接字。

ServerSocket是端口上的偵聽套接字。當客戶端連接到該端口上的ServerSocket時,ServerSocket.accept()方法將返回(普通)套接字。您的兩個端點之間的通信使用與此(普通)套接字關聯的輸入和輸出流。

關閉的ServerSocket只是停止監聽衆所周知的端口上,不涉及到建立插座。

0

插座存在於客戶端和服務器程序兩者。關閉任何套接字都會在另一端拋出異常。