繁体   English   中英

Java套接字服务器程序一段时间后不接受连接

[英]java socket server program not accepting connections after some time

我有一个套接字客户端应用程序,该应用程序侦听指定端口上主线程中的传入连接,接受传入连接并为每个连接启动一个用户线程。

此设置有一天会起作用,然后应用程序将停止接受任何新的新连接。 恢复的唯一方法是重新启动应用程序。 我不知道为什么会这样...这是我的主要角色,它为每个连接启动并启动一个新线程。

while(ServerOn)
   {
        ServerSocket myServerSocket;
        private static ArrayList<Socket> connecitons; 
    try {
        // Accept incoming connections.
        Socket conn = myServerSocket.accept();
        // adds the new connections to the socket
        connections.add(conn);

        // accept() will block until a client connects to the server.
        // If execution reaches this point, then it means that a client
        // socket has been accepted.

        // For each client, we will start a service thread to
        // service the client requests.

        // Start a Service thread

        ServerThread cliThread = new ServerThread(conn);
        cliThread.start();
        } catch (IOException ioe) {
            System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
            ioe.printStackTrace();
        }
    }
    try {
        myServerSocket.close();
        System.out.println("Server Stopped");
    } catch (Exception ioe) {
        System.out.println("Problem stopping server socket");
        System.exit(-1);
    }
    }

请帮忙。

编辑1

这是类声明:

class ServerThread extends Thread {
    Socket conn;
    boolean m_bRunThread = true;
    InputStream in = null;
    OutputStream outStream = null;



    //calling the 1-argument constructor with the socket parameters
    ServerThread(Socket s) {
        conn = s;
    }

    //Subclasses of Thread should override this method.
    public void run() {
    //lot of variables declared here.

    try {
            // Class InputStream is used for receiving data (as bytes) from client. 
            in = conn.getInputStream();
            // Class OutputStream is used for sending data (as bytes) to client.
            outStream = conn.getOutputStream();
            /*
             * 1. Go to Read Thread 
             * 2. Check for incoming data stream from Client 
             * 3. Go to read routine and process only if the data is received from the client 
             * 4. If there is no data for X minutes then close the socket.
             */
            conn.setSoTimeout(time in milliseconds);
            String inLine=null;

            while (m_bRunThread) {
                // read incoming stream
                while ((c=in.read(rec_data_in_byte))!= -1) 

                {...............

然后运行方法继续...

我的观察是基于您提供的上述代码。 我在下面看到的东西对我来说毫无疑问:

  1. private static ArrayList<Socket> connecitons;

我不需要此列表。 根据代码,我们总是为每个请求在此列表中添加conn对象。 我们不会在任何地方删除它们(我没有看到完整的代码)。 如果是这种情况,那么此列表的大小总是在增加。 并且可能导致OutOfMemoryError。

  1. while (m_bRunThread) {....}

在ServerThread类的run()方法中,变量m_bRunThread始终为true。 如果是这种情况,那么该线程将永远不会终止。 所以没有 活动线程的数量不断增加。 它将使应用程序无响应。 对于ConcurrentModificationException :由于您没有使用Iterator (或for-each循环)在列表上进行迭代,因此即使在多线程情况下也永远不会抛出此异常。

m_bRunThread上的外部循环应被删除。 您只需要内部读取循环,当它终止或遇到异常时,它应该关闭套接字。

我观察到的另一件事。 按照提供的代码,对于每个传入连接,您都在创建一个新的服务线程。 但是我不认为每次创建一个新线程都是一个好主意。

因为假设如果每秒有1000个连接,则意味着我们每秒创建1000个新线程,因此,这意味着管理1000个线程会产生很大的开销。

由于线程的上下文切换的开销,应用程序可能变得无响应。 其次,将有频繁的GC(垃圾收集器)循环,有时又可能导致STW(停止世界)这种情况。

所以我的建议是:

您可以使用某种线程池,可能是Executor框架,我们可以通过提供参数(例如核心池大小,最大池大小,保持空闲线程的存活时间等)来创建自己的ThreadPoolExecutor 因此,现在您不必管理线程的创建和生命周期。 现在可以重新使用空闲线程。 您的应用程序将具有更高的响应速度,因为频繁使用GC的机会会更少。

即使您可以使用Executor的框架内置固定大小的线程池实现,也不需要管理其余开销,除非您必须传递总编号。 参数中要存在的线程数,以供您处理请求。

下面是示例代码:

        private Executor executor = Executors.newFixedThreadPool(10);
        private ArrayList<Socket> connecitons = new ArrayList<>();
        while(ServerOn)
        {
            ServerSocket myServerSocket;

            try {
                // Accept incoming connections.
                Socket conn = myServerSocket.accept();
                connections.add(conn);

                executor.execute(new ServerThreadRunnable(conn));
            } catch (IOException ioe) {
                System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
                ioe.printStackTrace();
            }
        }
        try {
            myServerSocket.close();
            System.out.println("Server Stopped");
        } catch (Exception ioe) {
            System.out.println("Problem stopping server socket");
            System.exit(-1);
        }

下面是任务的实现。

class ServerThreadRunnable implements Runnable {
    private Socket conn;
    ServerThread(Socket s) {
        conn = s;
    }
    public void run() {
        //Here the implementation goes as per your requirement
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM