2010-12-01 130 views
0

在此應用程序中,我有一個等待客戶端連接的服務器套接字。我的問題是在監聽套接字退出時出現運行時異常。所以客戶端無法連接到系統。所以我需要重新啓動服務器。直到客戶端無法連接。以下我已經顯示了我的部分代碼。當服務器套接字退出偵聽時如何恢復

private Socket socket; 
private SSLServerSocket ssocket; 
private int port=6666; 

//here I have code need to create a serversocket 

while (listen) { 
    //wait for client to connect// 
    try{ 
     socket = ssocket.accept(); 
    } catch (IOException ioe) { 
     ioe.printStackTrace(); 
    }  
} 

如果發生異常,任何人都可以告訴我重新安裝到同一端口而不重新啓動服務器嗎?

回答

1

總結while循環進入另一個循環的同時,從來沒有退出並嘗試重新連接。

private Socket socket; 
private SSLServerSocket ssocket; 
private int port=6666; 

while(true) { 
    // Here I have code needed to create a ServerSocket 
    try { 
     connectToServerSocket(); 
    } catch (IOException) { 
     // log the exception 
     continue; 
    } 


    while (listen) { 
     // wait for client to connect 
     try{ 
      socket = ssocket.accept(); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     }  
    } 
} 
1

你必須關閉並重新打開的ServerSocket,然後開始接受連接

+0

我怎樣才能知道當一個未經檢查的異常發生。如果它被檢查異常,我可以捕獲並重新打開套接字。 – nath 2010-12-01 07:44:10

+0

@ganuke`try {...} catch(Throwable t){}`但是你應該確保你知道你可能捕獲的所有throwables。 – khachik 2010-12-01 07:47:37

1

The documentation不提什麼可能會導致接受IOException。看起來您可以在IOExceptionaccept之後繼續接受傳入連接。 man 2 accept介紹了以下可能出現的錯誤(加粗是我的):

[EBADF]   socket is not a valid file descriptor. - **doesn't make sence** 
[ECONNABORTED]  The connection to socket has been aborted. - **recoverable** 
[EFAULT]   The address parameter is not in a writable part of the user 
        address space. - **doesn't make sence** 
[EINTR]   The accept() system call was terminated by a signal. **not I/O** 
[EINVAL]   socket is unwilling to accept connections. **doesn't make sence** 
[EMFILE]   The per-process descriptor table is full. **??? Don't know** 
[ENFILE]   The system file table is full. **recoverable** 
[ENOMEM]   Insufficient memory was available to complete the operation. 
        **I'm not sure this will cause I/O** 

另一個選項是關閉的IOExceptions服務器套接字,並重新創建它。這樣可以在不重新啓動服務器的情況下再次監聽相同的端口,但當客戶端無法連接時會有時間間隔。

1

不用擔心。我已經結束了這個:

// maximum number of restarts for socket server 
private final AtomicLong reconnectCounter = new AtomicLong(MAX_RECONNECT); 

public void run() {  
    boolean reconnect = false;  
    ServerSocketChannel ssc = null; 
    ServerSocket serverSocket = null; 
    Thread t = Thread.currentThread();  
    try {   

     // handle pretty rare situation when exit flag was already set 
     if (t.isInterrupted()) { 
      Thread.interrupted(); 
      logger.error("Monitor thread was started with interrupted status set"); 
      return; 
     }  

     ssc = ServerSocketChannel.open();   
     final InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName(BIND_IP), conf.monitoringPort); 
     serverSocket = ssc.socket(); 
     serverSocket.bind(isa); 
     ssc.configureBlocking(false); // active polling mode       
     while (!t.isInterrupted()) { 
      boolean succ = false; 
      SocketChannel chan = null; 
      Socket s = null; 
      try {  
       chan = null; 
       s = null; 
       chan = ssc.accept();      
       if (chan != null) {      
        s = chan.socket(); 
        logger.error("Accepting message from @" + (s != null ? s.getRemoteSocketAddress() : "null")); 
        final long ts = createTimestamp(); 
        MonitorTask task = new MonitorTask(s, ts, MonitorPoolService.this, monitorEmailService); 
        ExecutorService exec = this.taskExecutor; 
        if (exec != null) { 
         exec.execute(task); 
         succ = true; 
        } else { 
         t.interrupt(); 
         break; // make sure loop exited - flag could change again 
        } 
       }  

       // Prevents 100% CPU 
       try { 
        Thread.sleep(1); 
       } catch (InterruptedException e) { 
        Thread.interrupted(); 
        logger.warn("Monitor thread was interrupted on wait"); // Printed on exit from JVM 
       } 
      } catch (Exception e) { 
       if (e instanceof IOException 
        && (! (e instanceof AsynchronousCloseException || e instanceof ClosedByInterruptException)) 
       ) reconnect = true; // reconnect only if some thread did not intendedly closed a connection  
       logger.error("Error in processing message from @" + (s != null ? s.getRemoteSocketAddress() : ""), e); 
      } finally {     
       try { 
        if (s != null && !succ) s.close(); 
       } catch (IOException e) { 
        logger.error("Error when closing socket to @" + (s != null ? s.getRemoteSocketAddress() : ""), e); 
       } finally {       
        try { 
         if (chan != null && !succ) chan.close(); 
        } catch (IOException e) { 
         logger.error("Error when closing socket channel to @" + (s != null ? s.getRemoteSocketAddress() : ""), e); 
        } 
       } 
      } 
     } 
    } catch (Exception e) { 
     if (e instanceof IOException) reconnect = true; 
     logger.error("Error in monitoring thread", e); 
    } finally { 
     try { 
      if (serverSocket != null) serverSocket.close(); 
     } catch (Exception e) { 
      if (e instanceof IOException) reconnect = true; 
      logger.error("Error when closing a server socket", e); 
     } finally { 
      try { 
       if (ssc != null) ssc.close(); 
      } catch (Exception e) { 
       if (e instanceof IOException) reconnect = true; 
       logger.error("Error when closing a server socket channel", e); 
      } 
     }          
    } 

    if (t.isInterrupted()) return; // interrupted - exit 
    if (!reconnect) return; // some IOExceptions can be handled by a reconnect  
    final long maxRestart = this.reconnectCounter.getAndDecrement(); // counter  
    if (maxRestart <= 0) return; // maxRestart reached - exit 
    restart(maxRestart - 1); // restart this runnable 
} 
0

試試這個。

ssocket.setReuseAddress(true);

socket.setReuseAddress(true);

相關問題