Java - Закрытие сокета при перезагрузке класса

Итак, я работаю на сервере для IRC, и я добавил экран конфигурации, где вы можете отредактировать порт, который он использует, но мне нужно повторно активировать Listen класс, чтобы он вступил в силу, поэтому у меня есть это в моем классе Config:

Listen.closePorts();
new Listen();

И вот мой класс Listen:

package server.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

import server.Server;
import server.gui.GUIMain;

public class Listen {
    private static Socket socket = null;
    private int port;

    public Listen() {
        try {
            port = Server.listenPort;
            @SuppressWarnings("resource")
            ServerSocket serverSocket = new ServerSocket(port);
            GUIMain.jta.append("\nServer Started and listening for messages on port " + port + ".\n");

            while(true) {
                socket = serverSocket.accept();
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String msg = br.readLine();
                GUIMain.jta.append("Received message from client: " + msg + "\n");
            }
        } catch (Exception e) {
            GUIMain.jta.append("Port " + port + " already in use!\n");
        } finally {
            try {
                socket.close();
            }  catch(Exception e) { }
        }
    }

    public static void closePorts() {
        try {
            socket.close();
            GUIMain.jta.append("Server closed\n");
        } catch (IOException e) { }
    }
}

Когда я запускаю приложение, оно запускает этот класс, открывая сокет с указанным портом, но когда я пытаюсь закрыть порт здесь:

public static void closePorts() {
    try {
        socket.close();
        GUIMain.jta.append("Server closed\n");
    } catch (IOException e) { }
}

Висит на socket.close();

И если я прокомментирую Listen.closePorts(); и попробуйте перезагрузить класс и оставив сокет открытым, он либо зависает, либо запускает catch() если порт совпадает с портом, который используется.

Короче говоря, как я могу закрыть сокет перед повторной инициализацией класса и использовать новый порт?

Вот полное исключение, которое он выбрасывает:

java.lang.NullPointerException
    at server.network.Listen.closePorts(Listen.java:44)
    at server.gui.GUISettings.actionPerformed(GUISettings.java:86)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

3 ответа

Решение

socket Переменная не присваивается до тех пор, пока клиент не сделает запрос. Если вы позвоните closePorts() до того, как это произойдет, ваша программа все еще будет socket = serverSocket.accept(); а также socket.close() вызовет исключение NullPointerException, потому что socket все равно будет нулевым.

См. http://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html для описания ServerSocket.accept().

Не предоставляя прямого решения, но никаких исключений не выдается, потому что ваш код поглощает их все. Пустые блоки улова никогда не являются хорошей практикой. По крайней мере, напечатайте трассировку стека перехваченного исключения, используя e.printStackTrace()

Здесь нет перезагрузки класса, и вам не нужно закрывать существующие клиентские сокеты. Просто закройте ServerSocket и заново создайте его на новом порту.

Другие вопросы по тегам