2012-10-17 25 views
1

我使用Oracle的Knock Knock示例編寫服務器和客戶端,從而當客戶端連接到服務器時,它會收到一個Knock Knock笑話來與之交互。一切都運行良好。Java套接字自動重啓服務器

雖然我的問題是當客戶端完成並斷開服務器程序終止的服務器本身。如果終止服務器,我可以讓它再次自動運行,以便它可以接受另一個客戶端的請求,而無需手動重新啓動服務器端?

下面是我的代碼,其中的評論顯示我卡在哪裏。我正在使用兩個在vmware播放器上運行的centos vm。

import java.net.*; 
import java.io.*; 

public class KnockKnockServer { 
    public static void main(String[] args) throws IOException { 
    server(); 
    /*HERE IS WHERE I AM STUCK 
    * If I call server() above in my main method everything runs great. 
    * However, I would like to put a timer or something inside main so that 
    * every second it checks to see if server() is still running and if not 
    * then start it up again. 
    */ 
    } 


    public static void server() throws IOException{ 
    ServerSocket serverSocket = null; 
     try { 
      serverSocket = new ServerSocket(4444); 
     } catch (IOException e) { 
      System.err.println("Could not listen on port: 4444."); 
      System.exit(1); 
     } 

     Socket clientSocket = null; 
     try { 
      clientSocket = serverSocket.accept(); 
     } catch (IOException e) { 
      System.err.println("Accept failed."); 
      System.exit(1); 
     } 

     PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); 
     BufferedReader in = new BufferedReader(
       new InputStreamReader(
       clientSocket.getInputStream())); 
     String inputLine, outputLine; 
     KnockKnockProtocol kkp = new KnockKnockProtocol(); 

     outputLine = kkp.processInput(null); 
     out.println(outputLine); 

     while ((inputLine = in.readLine()) != null) { 
      outputLine = kkp.processInput(inputLine); 
      out.println(outputLine); 
      if (outputLine.equals("Bye.")) 
       break; 
     } 
     out.close(); 
     in.close(); 
     clientSocket.close(); 
     serverSocket.close(); 
    } 
} 

回答

2

你可以移動的連接處理代碼到一個額外的線程(讓叫做KnockKnockHandler):

public class KnockKnockHandler extends Thread { 
    private Socket socket; 
    public KnockKnockWorker(Socket socket) { 
     this.socket = socket; 
    } 
    public void run() { 
     PrintWriter out = new PrintWriter(socket.getOutputStream(), true); 
     BufferedReader in = new BufferedReader(
      new InputStreamReader(
      socket.getInputStream())); 
     String inputLine, outputLine; 
     KnockKnockProtocol kkp = new KnockKnockProtocol(); 

     outputLine = kkp.processInput(null); 
     out.println(outputLine); 

     while ((inputLine = in.readLine()) != null) { 
      outputLine = kkp.processInput(inputLine); 
      out.println(outputLine); 
      if (outputLine.equals("Bye.")) 
       break; 
     } 
     out.close(); 
     in.close(); 
     socket.close(); 
    } 
} 

一旦有人訪問你的服務器創建KnockKnockHandler的新實例並啓動它:

try { 
    clientSocket = serverSocket.accept(); 
    KnockKnockHandler handler = new KnockKnockHandler(clientSocket); 
    handler.start(); 
} catch (IOException e) { 
    System.err.println("Accept failed."); 
    System.exit(1); 
} 

如果考慮到這個循環服務器永遠不會關閉(除拋出一個異常或者JVM終止; - )):

while(true) { 
    try { 
     clientSocket = serverSocket.accept(); 
     KnockKnockHandler handler = new KnockKnockHandler(clientSocket); 
     handler.start(); 
    } catch (IOException e) { 
     System.err.println("Accept failed."); 
     System.exit(1); 
    } 
} 

如果一個客戶端連接服務器將啓動一個新線程,進入循環的下一次迭代,等待下一個客戶端連接。

+0

在最後一塊代碼中,我在KnockKnockHandler處理程序= KnockKnockHandler(clientSocket)上得到一個錯誤。我用KnockKnockHandler handler = new KnockKnockHandler()替換它。 handler.KnockKnockWorker(clientSocket); – Chris

+0

它運行良好,謝謝! – Chris

2

您關閉serverSocket處理一個連接之後:

serverSocket.close(); 

你需要保持這個活着,移交給一個工作線程接收客戶端連接。

在你main方法,你會:

while (serverIsActive) { 
    clientSocket = serverSocket.accept(); 
    new ClientWorker(clientSocket).launch(); 
} 

ClientWorkerRunnable,並處理客戶端的連接:

public class ClientWorker implements Runnable { 

public ClientWorker(Socket clientSocket) { 
    this.clientSocket = clientSocket; 
} 

public void launch() { 
    new Thread(this).start(); 
} 

@Override 
public void run() { 
    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); 
    ...