2010-12-01 127 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);

相关问题