繁体   English   中英

"Java:在不关闭服务器的情况下无法关闭客户端连接"

[英]Java: can't close Client connection without closing Server

我在前一篇文章中写了一篇关于让双向服务器\/客户端套接字连接正常工作的文章。 我基本上已经成功了,但我还有一步作为障碍。 我想这样做,以便客户端在执行操作后断开连接,但服务器保持运行状态并且可以接受另一个客户端操作,直到客户端做出特定响应。 我试图通过客户端和服务器中的while循环来做到这一点。 这是我的服务器类:

import java.net.*;
import java.io.*;
public class ServerDemo {
    private Socket mySocket = null;
    private ServerSocket server = null;
    private static ObjectInputStream in=null;
    private static ObjectOutputStream out=null;
    private static Payload myPayload=new Payload();

    public ServerDemo(int port) throws ClassNotFoundException
    {
        double time=0;
        int bytes=0;
        try
        {
               server = new ServerSocket(port);
               System.out.println("Server started");
               System.out.println("Waiting for a client ...");
        }
        catch(IOException i)
        {
            System.out.println(i);
            myPayload.setRepeat(false);
        }
        try {
               while(myPayload.getRepeat()==true) {
               mySocket = server.accept();
               System.out.println("Client accepted");
               in = new ObjectInputStream(
                       new BufferedInputStream(mySocket.getInputStream()));
               out = new ObjectOutputStream(mySocket.getOutputStream());
               myPayload.setDataPasses(10);
               while (myPayload.getCurr()<myPayload.getDataPasses())
               {
                    try
                    {
                         myPayload= (Payload) in.readObject();
                         myPayload.raisePasses();
                         out.writeObject(myPayload);
                        
                    }
                    catch(IOException i)
                    {
                        System.out.println(i);
                        myPayload.setRepeat(false);
                    }
               }
               System.out.println("Closing connection");
               mySocket.close();
               in.close();
               System.out.println("Operation Complete");
               System.out.println("Client Address: "+myPayload.getClient());
               System.out.println("Server Address: "+myPayload.getServer());
               time=System.nanoTime()-(myPayload.getTime());
               time=time/1000000000;
               System.out.println("Total Time (in seconds): "+time);
               bytes=(int) ( ((myPayload.getPacket().length)*myPayload.getDataPasses())/time);
               System.out.println("Bytes per Second: "+bytes);
         }
        }
        catch(IOException i)
        {
            System.out.println(i);
            myPayload.setRepeat(false);
        }
    }
 
    public static void main(String[] args) throws ClassNotFoundException {
        // TODO Auto-generated method stub
        ServerDemo server=new ServerDemo(5000);
    }

}

我宁愿改变方法。 做这种事情的通常做法是创建一个线程来监听你的端口,然后,当客户端连接时,立即将新任务分派到线程池并继续监听。

这样,不仅您的服务器将在客户端断开连接后继续侦听,而且还能够并行服务多个客户端(直至线程池大小)。

另外请尽可能使用 try-with-resources 来轻松避免资源泄漏。

因此,您的代码可以更改为以下内容:

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServerDemo {
    private int port;
    private Thread listenThread;
    private ExecutorService serverPool;
    private static Payload myPayload = new Payload();

    public ServerDemo(int port) {
        this.port = port;
    }

    public synchronized void startServer() {
        serverPool = Executors.newFixedThreadPool(4);       

        listenThread = new Thread(() -> {
            try (ServerSocket serverSocket = new ServerSocket(port)) {
                System.out.println(String.format("Listening on port %d", port));
                while (!Thread.interrupted()) {
                    Socket clientSocket = serverSocket.accept();
                    serverPool.submit(new ClientTask(clientSocket));
                }
            } catch (IOException e) {
                System.err.println("Error processing client connection");
                e.printStackTrace();
            }
        });

        listenThread.start();
    }
    
    public synchronized void stopServer() {
        if (serverPool != null) {
            serverPool.shutdown();
            serverPool = null;
        }
        
        if(listenThread != null) {
            listenThread.interrupt();
            listenThread = null;
        }
    }

    private class ClientTask implements Runnable {
        private final Socket clientSocket;

        private ClientTask(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }

        @Override
        public void run() {
            System.out.println("Client accepted");
            try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(clientSocket.getInputStream()));
                ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream())) {
                myPayload.setDataPasses(10);
                while (myPayload.getCurr() < myPayload.getDataPasses()) {
                    try {
                        myPayload = (Payload) in.readObject();
                        myPayload.raisePasses();
                        out.writeObject(myPayload);
    
                    } catch (IOException i) {
                        System.out.println(i);
                        myPayload.setRepeat(false);
                    } catch (ClassNotFoundException e) {
                        System.err.println("Error finding class to deserialize");
                        e.printStackTrace();
                    }
                }
                System.out.println("Operation Complete");
                System.out.println("Client Address: " + myPayload.getClient());
                System.out.println("Server Address: " + myPayload.getServer());
                long time = System.nanoTime() - (myPayload.getTime());
                time = time / 1000000000;
                System.out.println("Total Time (in seconds): " + time);
                int bytes = (int) (((myPayload.getPacket().length) * myPayload.getDataPasses()) / time);
                System.out.println("Bytes per Second: " + bytes);
            } catch (IOException e1) {
                System.err.println("Error opening client I/O streams");
                e1.printStackTrace();
            }

            try {
                System.out.println("Closing connection");
                clientSocket.close();
            } catch (IOException e) {
                System.err.println("Error closing client connection");
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws ClassNotFoundException {
        ServerDemo server = new ServerDemo(5000);
        server.startServer();
        
        // do other stuff including trapping for sigterm, then call server.stopServer() if needed
    }

}

暂无
暂无

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

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