简体   繁体   English

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

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

I have a socket client application which listens for incoming connections in the main thread on a specified port,accepts incoming connections and starts a user thread for each connection. 我有一个套接字客户端应用程序,该应用程序侦听指定端口上主线程中的传入连接,接受传入连接并为每个连接启动一个用户线程。

this setup works for somedays and then the applicaiotns stops accepting any new new connections. 此设置有一天会起作用,然后应用程序将停止接受任何新的新连接。 the only way to recover is to restart the application. 恢复的唯一方法是重新启动应用程序。 I have no clue why this happens... here is my main which accpets and starts a new thread for each connection. 我不知道为什么会这样...这是我的主要角色,它为每个连接启动并启动一个新线程。

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);
    }
    }

please help. 请帮忙。

EDIT 1 编辑1

here is the class declaration: 这是类声明:

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) 

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

and the run method continues... 然后运行方法继续...

My observations are on the basis of the above code which you have provided. 我的观察是基于您提供的上述代码。 I am seeing below things which are little doubtful to me: 我在下面看到的东西对我来说毫无疑问:

  1. private static ArrayList<Socket> connecitons;

I am not getting the need of this list. 我不需要此列表。 As per the code, we are always adding the conn objects in this list for every request. 根据代码,我们总是为每个请求在此列表中添加conn对象。 We are not removing them anywhere(I have not seen full code). 我们不会在任何地方删除它们(我没有看到完整的代码)。 If this is the case then this list is always growing in size. 如果是这种情况,那么此列表的大小总是在增加。 And It may cause OutOfMemoryError. 并且可能导致OutOfMemoryError。

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

In the run() method of ServerThread class, Is the variable m_bRunThread always true. 在ServerThread类的run()方法中,变量m_bRunThread始终为true。 If this is the case then this thread will never get terminated. 如果是这种情况,那么该线程将永远不会终止。 So the no. 所以没有 of live threads keeps on increasing. 活动线程的数量不断增加。 It will make the application un-responsive. 它将使应用程序无响应。 For ConcurrentModificationException : As you are not using Iterator (or for-each loop) to iterate on list, so this exception will never be thrown even in case of multi-threaded scenario. 对于ConcurrentModificationException :由于您没有使用Iterator (或for-each循环)在列表上进行迭代,因此即使在多线程情况下也永远不会抛出此异常。

The outer loop on m_bRunThread should be removed. m_bRunThread上的外部循环应被删除。 You only need the inner read loop, and it should close the socket when it terminates or gets an exception. 您只需要内部读取循环,当它终止或遇到异常时,它应该关闭套接字。

One more thing I have observed. 我观察到的另一件事。 As per the provided code, for every incoming connection, you are creating a new service thread. 按照提供的代码,对于每个传入连接,您都在创建一个新的服务线程。 But I don't think that every time to create a new thread is good idea. 但是我不认为每次创建一个新线程都是一个好主意。

Because suppose If there are 1000 connections/second, it means we are creating new 1000 threads per second, so It means its a big overhead to manage 1000 threads. 因为假设如果每秒有1000个连接,则意味着我们每秒创建1000个新线程,因此,这意味着管理1000个线程会产生很大的开销。

The application may become non-responsive due to the overhead of context-switches of threads. 由于线程的上下文切换的开销,应用程序可能变得无响应。 Secondly there will be frequent GC(garbage collector) cycles, which again sometimes may result into STW(stop the world) kind of situation. 其次,将有频繁的GC(垃圾收集器)循环,有时又可能导致STW(停止世界)这种情况。

So my advice is: 所以我的建议是:

You can use some kind of thread pool, may be Executor framework and we can create our own ThreadPoolExecutor by providing the parameters(such as core pool size, maximum pool size, keep alive time for an idle thread etc). 您可以使用某种线程池,可能是Executor框架,我们可以通过提供参数(例如核心池大小,最大池大小,保持空闲线程的存活时间等)来创建自己的ThreadPoolExecutor So now you don't have to manage the creation and lifecycle of threads. 因此,现在您不必管理线程的创建和生命周期。 Now the idle threads can be re-used. 现在可以重新使用空闲线程。 Your application will be more responsive as the chances of frequent GCs will be less. 您的应用程序将具有更高的响应速度,因为频繁使用GC的机会会更少。

Even you can go for Executor's framework in-build fixed sized thread pool, implementation, with this you don't need to manage the rest overhead, except one thing that you have to pass the total no. 即使您可以使用Executor的框架内置固定大小的线程池实现,也不需要管理其余开销,除非您必须传递总编号。 of threads in parameter, which you want to be there to serve the requests. 参数中要存在的线程数,以供您处理请求。

Below is the sample code: 下面是示例代码:

        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);
        }

Below is the task implementation.. 下面是任务的实现。

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