SocketException:套接字关闭

3
我正在使用Java Sockets创建一个聊天应用程序,当关闭服务器时,会出现SocketException:socket closed的错误。即使我从未尝试连接客户端,只要停止服务器,就会出现这个套接字关闭异常 我知道这个错误的意思,我试图在套接字已经关闭后访问它,但是我无法弄清楚为什么会发生这种情况。
public ServerSocket server_socket;
new ConnectionThread(server_back_end);

class ConnectionThread extends Thread implements Runnable, Serializable
{
    public ServerBackEnd server_back_end;

    public ConnectionThread(ServerBackEnd server_back_end) /*constructor*/
    {
        this.server_back_end = server_back_end;
        start();
    }

    @Override
    public void run()
    {
        try
        {
            server_back_end.server_socket = new ServerSocket(8080);
            server_back_end.server_front_end.display("<<SERVER STARTED>>");

            while (server_back_end.running)
                add_incoming_clients();
        }
        catch (Exception e)
        {
            e.printStackTrace(); //this gets thrown when I stop server
        }
    }//end run()

我认为问题在于add_incoming_clients()函数中,因为当我注释掉它的调用时,就不会出现错误。即使我没有处理任何客户端,也会在accept()方法处发生某些情况:

    public void add_incoming_clients() throws IOException, ClassNotFoundException
    {
        Socket client_socket = server_back_end.server_socket.accept(); //line 172

        ClientInfo new_client = new ClientInfo(
                new ObjectOutputStream(client_socket.getOutputStream()),
                new ObjectInputStream(client_socket.getInputStream()));
     //...
     //...
    }

当我停止服务器时,这里是代码:

 public void stop()
    {
        if (running)
            try
            {
                running = false;
                server_socket.close();
                server_front_end.display("<<SERVER TERMINATED>>");
            }
            catch (IOException e)
            {
                System.out.println("stop server exception, is not the problem");
            }
    }//end stop()

有人能解释一下我必须怎么做才能正确关闭它而不出现异常吗?这是错误信息(似乎是第172行有问题,但我不明白为什么)

java.net.SocketException: socket closed
    at java.net.DualStackPlainSocketImpl.accept0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
    at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
    at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
    at java.net.ServerSocket.implAccept(ServerSocket.java:545)
    at java.net.ServerSocket.accept(ServerSocket.java:513)
    at ConnectionThread.add_incoming_clients(ServerBackEnd.java:172)
    at ConnectionThread.run(ServerBackEnd.java:159)
2个回答

3

这个异常是你的好朋友。它释放了等待在ServerSocket.accept()上的线程,适当的处理可以让你在完全关闭之前清理任何需要清理的东西...你需要像对待朋友一样对待它 :)


哦!我不知道!我一直在尽可能正确地编程,认为这个异常不是“朋友”。现在你解释了,它有意义了。谢谢!! - user3487243
@user3487243 不用谢。顺便说一下,你可能想把你的代码改成捕获(SocketException ex)来捕获这种异常而不是其他种类的异常。这也可以在代码中“记录”发生了什么。 - ControlAltDel
好的,很棒。就程序运行而言,我想这不会有太大的影响吧?这只是为了明确地捕获特定的异常。 - user3487243
@user3487243 是的。就像我说的那样,这将使下一个接手你代码的人更清楚。 - ControlAltDel

1

查看代码和跟踪信息,当您调用stop()时,第一件事是通知连接线程停止其活动,然后在确认连接线程已停止后再继续执行stop方法。

有可能发生的情况是,在连接线程正在使用套接字时,stop强制关闭了套接字。可以在跟踪信息中看到这一点。


我该如何通知连接线程?我以为我只能关闭套接字然后离开? - user3487243
有几种机制可以在线程之间进行通信。您可以共享一个变量标志,并使线程停止,如果该标志变为 true 或 false(并在 stop() 函数中编辑该标志)。这就是他们在这里建议的:https://dev59.com/dnRB5IYBdhLWcg3wSVcI - rdavb
啊,是的。我用布尔变量running来做这个。不过还是谢谢你提醒我! - user3487243

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接