Java 多线程处理 Socket Too many open files异常

发布于 2022-09-07 11:37:56 字数 7377 浏览 28 评论 0

在本地机器上做了一次Java Socket的多线程的实验,server和client在,思路是server和client都想用多线程处理,且socket相重复利用,结果遇到异常。
描述一下及其环境:
3.1 GHz Intel Core i7
16 GB 1867 MHz DDR3,

➜  Client git:(2.0-SNAPSHOT) ✗ ulimit -a                                                       
-t: cpu time (seconds)              unlimited
-f: file size (blocks)              unlimited
-d: data seg size (kbytes)          unlimited
-s: stack size (kbytes)             8192
-c: core file size (blocks)         0
-v: address space (kbytes)          unlimited
-l: locked-in-memory size (kbytes)  unlimited
-u: processes                       2128
-n: file descriptors                1048600
➜  Client git:(2.0-SNAPSHOT) ✗ sysctl net.inet.ip.portrange                                    
net.inet.ip.portrange.lowfirst: 1023
net.inet.ip.portrange.lowlast: 600
net.inet.ip.portrange.first: 1024
net.inet.ip.portrange.last: 65535
net.inet.ip.portrange.hifirst: 49152
net.inet.ip.portrange.hilast: 65535
➜  Client git:(2.0-SNAPSHOT) ✗ 

Server端代码:

public class EchoServer {

    public static ExecutorService executorService;
    public static final String NEWLINE = "\r\n";
    public static long COUNT = 0;

    public EchoServer(int port) throws IOException {
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress("127.0.0.1", port));
        System.out.println("Starting echo server on port: " + port);
        while (true) {
            long start = System.currentTimeMillis();
            COUNT++;
            Socket socket = serverSocket.accept();
            ProcessTask processTask = new ProcessTask(socket, start);
            executorService.execute(processTask);
        }
    }

    public static void main(String[] args) throws IOException {
        executorService = Executors.newFixedThreadPool(5 * Runtime.getRuntime().availableProcessors());
        new EchoServer(9999);
    }

    public static class ProcessTask implements Runnable {

        private Socket socket;
        private long startTime;

        public ProcessTask(Socket socket, long startTime) {
            this.socket = socket;
            this.startTime = startTime;
        }

        public void run() {
            BufferedReader br = null;
            PrintWriter out = null;

            try {
                br = getReader(socket);
                out = getWriter(socket);

                String msg;
                while ((msg = br.readLine()) != null) {

                    String res = "Server Reply : " + msg;
                    out.println(res);
                    out.flush();
                }
                long end = System.currentTimeMillis();
                System.out.println("Closing connection with client. 耗时 : " + ((end - startTime)));
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.shutdownInput();
                    socket.shutdownOutput();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private PrintWriter getWriter(Socket socket) throws IOException {
            OutputStream socketOut = socket.getOutputStream();
            return new PrintWriter(socketOut, true);
        }

        private BufferedReader getReader(Socket socket) throws IOException {
            InputStream socketIn = socket.getInputStream();
            return new BufferedReader(new InputStreamReader(socketIn));
        }
    }
}

Client代码:

public class EchoClient {

    public static final int port = 9999;
    public static final String NEWLINE = "\r\n";
    public static final long NANOSECONDS_PER_SECOND = 1000 * 1000 * 1000;
    public static final long REQUESTS_PER_SECOND    = 1000 * 1000;

    public static long COUNT = 0;

    public static void main(String args[]) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                50, 50, 3000L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>());

        List<Task> tasks = new ArrayList<>();

        for (int i = 0; i < 10000; i++) {
            tasks.add(new Task(i, port));
        }

        boolean flag = false;
        while (true) {
            tasks.stream().forEach(
                    task ->
                    {
                        threadPoolExecutor.submit(task);
                        COUNT++;
                        try {
                            long sleep_time = NANOSECONDS_PER_SECOND / REQUESTS_PER_SECOND;
                            TimeUnit.NANOSECONDS.sleep(sleep_time);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
            );
            if (flag) {
                break;
            }
        }

        threadPoolExecutor.shutdown();
    }

    public static class Task implements Callable<Long> {

        private int port;
        private int id;
        private String taskName;

        public Task(int id, int port) {
            this.id = id;
            this.port = port;
            this.taskName = "Client_" + this.id;
        }

        public Long call() {
            long start = -1;
            long end = -1;
            try {
                Socket socket = new Socket("127.0.0.1", port);
                start = System.currentTimeMillis();
                String msg = "From " + taskName;
                msg = msg + NEWLINE;
                for (int i = 1; i <= 1; i++) {
                    OutputStream socketOut = null;
                    BufferedReader br = null;
                    try {
                        socketOut = socket.getOutputStream();
                        socketOut.write(msg.getBytes());
                        socketOut.flush();

                        br = new BufferedReader(new InputStreamReader(
                                socket.getInputStream()));
                        String res = br.readLine();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        socket.shutdownInput();
                        socket.shutdownOutput();
                    }
                }
                end = System.currentTimeMillis();

                System.out.println(taskName + " 完成发送数据!" + " 耗时 : " + ((end - start)));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return (end - start);
        }
    }
}

刚开始运行没有问题,大概运行25分钟之后会出现入下异常:

java.net.SocketException: Too many open files
    at java.net.Socket.createImpl(Socket.java:460)
    at java.net.Socket.<init>(Socket.java:431)
    at java.net.Socket.<init>(Socket.java:211)
    at com.study.base.EchoClient$Task.call(EchoClient.java:68)
    at com.study.base.EchoClient$Task.call(EchoClient.java:52)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

各位大佬帮忙看看是哪个地方认识的有误区还是配置问题?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

守不住的情 2022-09-14 11:37:56

貌似没看到close或者try with resource
所以应该是socket没关

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文