Java:如何毫无例外地停止服务器(关闭套接字)? [英] Java: how to stop a server (close a Socket) without an exception?

查看:125
本文介绍了Java:如何毫无例外地停止服务器(关闭套接字)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经制作了一个服务器,该服务器可以加入许多客户端.
但是我有问题.
我添加了启动/停止按钮,它应该启动/停止服务器.但是代码无法按我想要的方式工作:未关闭连接,代码转到IOException这是问题"(在ServerLogic部分中).
此外,客户端仍然可以与服务器联系.

I've made a server which allows to join many clients.
However I have a problem.
I added START/STOP button which should start/stop server. But the code does not work like I want: connection isn't closed and code goes to the IOException "THIS IS PROBLEM" (in ServerLogic part).
Additionally clients still can contact with server.

服务器逻辑

public class ServerLogic
{

private static ServerSocket m_sSocket;
private static Set<ServerSubscriber> m_subscriberList = new HashSet<ServerSubscriber>();
private static boolean m_isServerRun = false;

private static class ServerLogicHolder
{
    static final ServerLogic INSTANCE = new ServerLogic();
}


private ServerLogic()
{}


public static ServerLogic getServerLogic()
{
    return ServerLogicHolder.INSTANCE;
}


/**
 * It starts listening of incoming connections from the clients.
 * 
 * @param port
 */
public void startListening(int port)
{
    try
    {
        if (!m_isServerRun)
        {
            m_sSocket = new ServerSocket(port);
            K6s.getUiServerConsole().addLine(Config.LOG_START);
            m_isServerRun = true;
        }
        else
        {
            System.out.println(Config.LOG_ERROR1);
        }
    }
    catch (IOException e)
    {
        System.out.println(Config.LOG_ERROR1);
    }

    try
    {
        while (isServerRun())
        {
            new Thread(new ServerSubscriber(m_sSocket.accept(), K6s.getUiServerConsole())).start();
        }
    }
    catch (IOException e1)
    {
        /*
         java.net.SocketException: socket closed
         at java.net.DualStackPlainSocketImpl.accept0(Native Method)
         at java.net.DualStackPlainSocketImpl.socketAccept(Unknown Source)
         at java.net.AbstractPlainSocketImpl.accept(Unknown Source)
         at java.net.PlainSocketImpl.accept(Unknown Source)
         at java.net.ServerSocket.implAccept(Unknown Source)
         at java.net.ServerSocket.accept(Unknown Source)
         at org.czarny.k6s.comm.ServerLogic.startListening(ServerLogic.java:69)
         at org.czarny.k6s.gui.K6s$2$1.run(K6s.java:138)
         at java.lang.Thread.run(Unknown Source)
        */
    }
}


/**
 * Just close server's socket.
 */
public void stopListening()
{
    if (m_isServerRun)
    {
        try
        {
            m_isServerRun = false;
            m_sSocket.close();
            m_sSocket = null;
        }
        catch (IOException e)
        {
            m_isServerRun = true;
            System.out.println(Config.LOG_ERROR4);
        }
    }
}


public HashSet<ServerSubscriber> getSubscriberList()
{
    return (HashSet<ServerSubscriber>) m_subscriberList;
}


public boolean isServerRun()
{
    return m_isServerRun;
}
}

客户订阅者(未删除不必要的代码)

CLIENT SUBSCRIBER (not neccessary code has been removed)

public class ServerSubscriber implements Runnable
{

private Socket m_socket;
private LogComponent m_serverConsole;
private PrintWriter m_outComm;

private String m_subscriberIP;
private String m_subscriberName;
private String m_subsctiberLogInfo;


ServerSubscriber(Socket socket, LogComponent serverConsole)
{
    m_socket = socket;
    m_serverConsole = serverConsole;
    try
    {
        m_outComm = new PrintWriter(socket.getOutputStream(), true);
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    sendMessage(Config.MSG_HANDSHAKE);
}


/**
 * This method runs messages from this subscriber.
 */
public void run()
{
    String line;
    BufferedReader inComm = null;

    try
    {
        inComm = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));
    }
    catch (IOException e)
    {
        m_serverConsole.addLine(Config.LOG_ERROR3);
    }

    while (ServerLogic.getServerLogic().isServerRun())
    {
        try
        {
            //do something here
    }
}
}

用于处理START/STOP的按钮

Button which handles START/STOP

uiStart.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent arg0)
        {
            if (!ServerLogic.getServerLogic().isServerRun())
            {
                uiStart.setText(Config.GUI_BTN_STOP);
                new Thread(new Runnable()
                {
                    public void run()
                    {
                        try
                        {
                            ServerLogic.getServerLogic().startListening(Integer.parseInt(uiServerPort.getText()));
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
            else
            {
                ServerLogic.getServerLogic().stopListening();
                m_uiServerConsole.addLine(Config.LOG_STOP);
                uiStart.setText(Config.GUI_BTN_START);
            }
        }
    });

我错过了什么?
如何正确关闭连接而没有任何异常?
我是否应该在关闭Socket之前向所有客户端发送一些要求关闭的消息,或者仅在服务器上关闭Socket就足够了?
问候.

What I missed?
How to properly close connection without any exceptions?
Should I just before closing the Socket send to all clients some message with demand of closeure or just closing the Socket on the server should be enough?
Regards.

推荐答案

我添加了START/STOP按钮,该按钮应该启动/停止服务器.但是代码无法按我想要的方式工作:连接未关闭

I added START/STOP button which should start/stop server. But the code does not work like I want: connection isn't closed

那是因为您要关闭ServerSocket,而不是接受的套接字.

That's because you're closing the ServerSocket, not an accepted socket.

并且代码转到IOException这是问题"(在ServerLogic部分中).

and code goes to the IOException "THIS IS PROBLEM" (in ServerLogic part).

那是正常的.这里没事.

That's normal. Nothing wrong here.

此外,客户端仍然可以与服务器联系.

Additionally clients still can contact with server.

现有客户端可以继续使用其现有连接.如果要关闭它们,请参见下一步.无法创建连接.

Existing clients can continue to use their existing connections. If you want to close those, see next. No new connections can be created.

如何正常关闭连接而没有任何异常?

How to properly close connection without any exceptions?

将其关闭以进行输入.这将导致读取导致流结束,这应该已经导致相关线程关闭套接字并退出.

Shut them down for input. That will cause the reads to incur an end of stream, which should already cause the threads concerned to close the socket and exit.

我是否应该在关闭Socket之前向所有客户端发送一些消息,要求关闭消息或仅在服务器上关闭Socket就足够了?

Should I just before closing the Socket send to all clients some message with demand of closeure or just closing the Socket on the server should be enough?

关闭插座就足够了.发送额外的消息不会增加任何价值.客户端将从其读取中获得通常的流结束指示,或者在其写入中获得IOException: connection reset.

Closing the socket is sufficient. Sending an extra message doesn't add any value. The clients will get the usual end-of-stream indications from their reads, or an IOException: connection reset on their writes.

这篇关于Java:如何毫无例外地停止服务器(关闭套接字)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆