2010-12-01 8 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

の受け入れを開始する必要があります。

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

あなたは決して終了しないと再接続しようとするさらに別のwhileループにあなたのwhileループをラップ閉じてServerSocketを再度開くと、その後の接続

+0

。それがチェックされている場合は、私はそれをキャッチして、ソケットを再び開くことができます。 – nath

+0

@ganuke 'try {...} catch(Throwable t){}'しかし、あなたがそこにキャッチする可能性があるすべてのスローバイドを知っていることを確認する必要があります。 – khachik

+0

@khachikはすべてのチェックされていない例外やエラーなどをキャッチすることができます – nath

1

The documentation受け入れるにIOExceptionを引き起こす可能性がどのように言及していません。 IOExceptionの後に着信接続を引き続き受け入れることができるようです。acceptです。 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上のサーバソケットを閉じて、もう一度それを作成することです。これにより、サーバーを再起動せずに同じポートを再試行することができますが、クライアントが接続できない場合には時間差が生じます。

+0

EFAULTはJavaでは意味がありません* EINVALはリッスンソケットではないことを意味しますが、これはJavaでは発生しません。 EMFILEとENFILEは、いくつかのfdがクローズされた後に回復可能です。 ENOMEMは、メモリが利用可能になると回復可能です。 EINTRはJavaによって処理されます。他のものは回収できません。 – EJP

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);

関連する問題