Как восстановить, когда сокет сервера выходит из прослушивания - PullRequest
0 голосов
/ 01 декабря 2010

В этом приложении у меня есть сокет сервера, который ожидает подключения клиентов.Моя проблема - когда во время прослушивания выход сокета из прослушивания происходит исключение во время выполнения.Таким образом, клиенты не могут подключиться к системе.Поэтому мне нужно перезагрузить сервер.До этого клиенты не могут подключиться.После я показал часть своего кода.

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

Может ли кто-нибудь предложить мне способ присоединиться к тому же порту без перезапуска сервера, если произошло исключение?

Ответы [ 5 ]

1 голос
/ 29 августа 2012

Не беспокойся.Я закончил с этим:

// 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
}
1 голос
/ 01 декабря 2010

Оберните ваш цикл while в еще один цикл while, который никогда не выходит и пытается восстановить соединение.

1 голос
/ 01 декабря 2010

В документации не указано, что может вызвать 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 и создать его заново. Это позволяет снова прослушивать тот же порт без перезапуска сервера, но при невозможности подключения клиентов будет временной промежуток.

1 голос
/ 01 декабря 2010

вам придется закрыть и снова открыть ServerSocket, а затем начать принимать подключения

0 голосов
/ 30 мая 2015

Попробуй это.

ssocket.setReuseAddress(true);

socket.setReuseAddress(true);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...