自学内容网 自学内容网

BIO示例代码

一个请求开一个线程

package org.example.demo;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author hrui
 * @date 2024/7/27 11:28
 */
public class BIOServer {

    public static void main(String[] args) throws IOException {
        // 创建线程池

        //思路
        //1.创建一个线程池
        //2.如果有客户端连接,就创建一个线程,与之通讯(单独写一个方法处理)

        ExecutorService executorService = Executors.newCachedThreadPool();

        //创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务器启动了");
        while (true) {
            //监听,等待客户端连接
            final Socket socket = serverSocket.accept();
            System.out.println("一个客户端连接了");
            //创建一个线程,与客户端通讯
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    //和客户端通讯
                    handler(socket);
                }
            });
        }

    }

    private static void handler(Socket socket) {
        System.out.println("线程信息,id=" + Thread.currentThread().getId() + ",名字=" + Thread.currentThread().getName());
        try {
            byte[] bytes = new byte[1024];
            InputStream inputStream = socket.getInputStream();
            while (true) {
                int len = inputStream.read(bytes);
                if (len != -1) {
                    System.out.println(new String(bytes, 0, len));
                    if ("exit".equals(new String(bytes, 0, len).trim())) {
                        System.out.println("主动断开连接");
                        socket.close();
                        break;
                    }
                }else {
                    break;
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                socket.close();
            }catch (IOException e){
                e.printStackTrace();
            }

        }
    }
}

然后window+R

telnet 127.0.0.1 8888

ctrl+]  

通过send命令发送数据

当客户端连接之后,没有发送数据前  

也可以自己编写Socket Client

package org.example.demo;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author hrui
 * @date 2024/7/27 12:00
 */
public class BIOClient {
    public static void main(String[] args) {
        Socket socket = null;
        PrintWriter writer = null;
        Scanner scanner = new Scanner(System.in);

        try {
            // 1. 连接到本地运行的端口为 8888 的服务器
            socket = new Socket("localhost", 8888);
            System.out.println("已连接到服务器。");

            // 2. 创建一个输出流,用于向服务器发送数据
            OutputStream outputStream = socket.getOutputStream();
            writer = new PrintWriter(outputStream, true);

            // 3. 循环发送消息到服务器
            String message;
            while (true) {
                System.out.println("请输入要发送到服务器的消息(输入 'exit' 结束会话):");
                message = scanner.nextLine();
                writer.println(message);
                if ("exit".equalsIgnoreCase(message.trim())) {
                    System.out.println("退出会话。");
                    break;
                }
            }

            // 4. 可选地,这里可以读取服务器的响应
            // 为简洁起见,这个示例不包括服务器响应处理

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 5. 关闭资源
            try {
                if (writer != null) {
                    writer.close();
                }
                if (socket != null) {
                    socket.close();
                }
                System.out.println("客户端连接已关闭。");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

 直接用BufferedReader

package org.example.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author hrui
 * @date 2024/7/27 12:24
 */
public class BIOServer2 {
    public static void main(String[] args) throws IOException {
        // 创建线程池
        ExecutorService executorService = Executors.newCachedThreadPool();

        // 创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务器启动了");
        System.out.println("等待客户端连接");

        while (true) {
            // 监听,等待客户端连接
            final Socket socket = serverSocket.accept();
            System.out.println("一个客户端连接了");

            // 创建一个线程,与客户端通讯
            executorService.execute(() -> handler(socket));
        }
    }

    private static void handler(Socket socket) {
        System.out.println("线程信息,id=" + Thread.currentThread().getId() + ",名字=" + Thread.currentThread().getName());
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))){
            String line;
            System.out.println("收到客户端消息");
            while ((line = reader.readLine()) != null) {
                // 实时输出接收到的消息
                System.out.println("收到的消息: " + line);
                // 检查是否包含结束标志
                if (line.trim().equalsIgnoreCase("exit")) {
                    System.out.println("客户端请求断开连接");
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                System.out.println("连接已关闭。");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Java BIO问题分析

每个请求都需要创建独立线程,与对应客户端进行数据的 Read和Writer

当并发数量较大时,需要创建大量线程来处理连接,导致系统资源占用较大

连接建立之后,如果当前线程在那时没有数据可读,则线程阻塞在Read操作上,造成线程资源浪费


原文地址:https://blog.csdn.net/tiantiantbtb/article/details/140733414

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!