【问题标题】:Java - Closing socket when reloading classJava - 重新加载类时关闭套接字
【发布时间】:2013-02-28 12:44:02
【问题描述】:

所以我正在为 IRC 开发服务器,我添加了一个配置屏幕,您可以在其中编辑它正在使用的端口,但我必须重新初始化 Listen 类才能使其生效,所以我有这在我的 Config 类中:

Listen.closePorts();
new 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)

【问题讨论】:

  • 是否抛出异常?挂了多久?
  • 它没有抛出异常,它只是挂起,过了一会儿我只是在任务管理器中强制关闭应用程序
  • 您似乎尝试关闭同一个套接字两次?您的 finally 块会关闭套接字,如果您在此之后调用 closePorts 可能会导致问题。
  • 不确定,直到使用 try 或 catch 块完成后才会运行,对吧?
  • 不会抛出异常,因为您的代码正在吞噬它们。空的 catch 块从来都不是好习惯。至少,打印捕获的异常的堆栈跟踪。

标签: java sockets port reload


【解决方案1】:

不提供直接解决方案,但不会引发异常,因为您的代码正在吞噬它们。空的 catch 块从来都不是好习惯。至少,使用 e.printStackTrace() 打印捕获的异常的堆栈跟踪

【讨论】:

  • 好的,我用 e.printStackTrace 试过了;它出现 java.lang.NullPointerException 错误,但套接字应该正在运行/等待消息,所以它不能为空,对吗?
  • 你能显示完整的跟踪吗?您是否能够围绕导致问题的线路进行调试?
【解决方案2】:

socket 变量直到客户端发出请求后才被分配。如果您在此之前调用closePorts(),您的程序仍将在socket = serverSocket.accept(); 等待,而socket.close() 将抛出NullPointerException,因为socket 仍将为null。

有关 ServerSocket.accept() 的说明,请参阅 http://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#accept()

【讨论】:

  • 那么如何阻止它等待客户端连接?
  • 您可以致电setSoTimeout(milliseconds) 之前 socket = serverSocket.accept()。这将导致它仅阻塞指定的时间段,之后它将引发SocketTimeoutException。见docs.oracle.com/javase/7/docs/api/java/net/…
【解决方案3】:

这里没有类重新加载,你不需要关闭现有客户端接受的套接字。只需关闭 ServerSocket 并在新端口上重新创建它。

【讨论】:

    猜你喜欢
    • 2018-02-14
    • 1970-01-01
    • 2014-09-09
    • 2018-05-11
    • 2014-03-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多