美文网首页
BIO阻塞式网络编程

BIO阻塞式网络编程

作者: 佐蓝Gogoing | 来源:发表于2019-05-21 21:22 被阅读0次

1. 简单的 C/S 程序

public class BIOServer {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("服务启动成功");
            while (!serverSocket.isClosed()) {
                Socket requset = serverSocket.accept();
                System.out.println("收到新连接" + requset.toString());
                
                InputStream inputStream = requset.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String msg;
                while ((msg = bufferedReader.readLine()) != null) {
                    if (msg.length() == 0) {
                        break;
                    }
                    System.out.println(msg);
                }
                System.out.println("收到数据,来自" + requset.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

首先要在服务端new ServerSocket,这是 Java 程序提供好的,它会去监听指定的端口。
如果需要接收客户端发送给的请求的话,需要调用它的accept() 方法,这个方法是阻塞的,所谓阻塞就是如果没有收到请求的话,这个方法会一直等待,从方法注释中可以看到这个阻塞的提示

这个例子通过请求 socket 对象,配合 io 操作把收到的请求打印出来。
下面是客户端的代码

public class BIOClient {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 8080);
            OutputStream outputStream = socket.getOutputStream();
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入");
            String smg = scanner.nextLine();
            outputStream.write(smg.getBytes(StandardCharsets.UTF_8));
            scanner.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

启动服务端,然后客户端使用socket对象配合 io 将数据发送给客户端,输入今天是个好日子

请输入
今天是个好日子

Process finished with exit code 0

因为OutputStream也是阻塞的,所以看到程序退出,就说明发送成功了。
再看服务端的输出,如下

服务启动成功
收到新连接Socket[addr=/127.0.0.1,port=11956,localport=8080]
今天是个好日子
收到数据,来自Socket[addr=/127.0.0.1,port=11956,localport=8080]

2. 多线程处理

这个服务端接到一个连接后,其他连接就只能等待第一个连接结束,明显不符合使用要求。
因为阻塞是阻塞的线程,所以可以在处理的部分加入多线程的处理,这样就可以同时处理多个连接。

public class BIOServer2 {

    private static ExecutorService threadPool = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("服务启动成功");
            while (!serverSocket.isClosed()) {
                Socket requset = serverSocket.accept();
                System.out.println("收到新连接" + requset.toString());
                threadPool.execute(() -> {
                    try {
                        InputStream inputStream = requset.getInputStream();
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                        String msg;
                        while ((msg = bufferedReader.readLine()) != null) {
                            if (msg.length() == 0) {
                                break;
                            }
                            System.out.println(msg);
                        }
                        System.out.println("收到数据,来自" + requset.toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

启动服务端,然后同时启动两个客户端,输入不同的文字,都能打印出来

服务启动成功
收到新连接Socket[addr=/127.0.0.1,port=12053,localport=8080]
收到新连接Socket[addr=/127.0.0.1,port=12063,localport=8080]
123
收到数据,来自Socket[addr=/127.0.0.1,port=12053,localport=8080]
456
收到数据,来自Socket[addr=/127.0.0.1,port=12063,localport=8080]

3.回应 HTTP 请求

在浏览器中输入127.0.0.1:8080,会显示如下的错误消息

但是后台是能够接收到数据的

服务启动成功
收到新连接Socket[addr=/127.0.0.1,port=12284,localport=8080]
收到新连接Socket[addr=/127.0.0.1,port=12285,localport=8080]
GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.158 Safari/537.36 Vivaldi/2.5.1525.43
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
收到数据,来自Socket[addr=/127.0.0.1,port=12284,localport=8080]

这时在request的输出流中加入 HTTP 的响应报文,浏览器就能显示出来了

public class BIOServer3 {

    private static ExecutorService threadPool = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("服务启动成功");
            while (!serverSocket.isClosed()) {
                Socket requset = serverSocket.accept();
                System.out.println("收到新连接" + requset.toString());
                threadPool.execute(() -> {
                    try {
                        InputStream inputStream = requset.getInputStream();
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                        String msg;
                        while ((msg = bufferedReader.readLine()) != null) {
                            if (msg.length() == 0) {
                                break;
                            }
                            System.out.println(msg);
                        }
                        System.out.println("收到数据,来自" + requset.toString());
                        OutputStream outputStream = requset.getOutputStream();
                        outputStream.write("HTTP/1.1 200 OK\r\n".getBytes());
                        outputStream.write("Content-Length: 11\r\n\r\n".getBytes());
                        outputStream.write("Hello World".getBytes());
                        outputStream.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (requset != null)
                                requset.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

相关文章

  • BIO阻塞式网络编程

    1. 简单的 C/S 程序 首先要在服务端new ServerSocket,这是 Java 程序提供好的,它会去监...

  • 2.1.2 BIO阻塞式网络编程

    BIO - 阻塞IO的含义 阻塞(blocking) IO: 资源不可用时,IO请求一直阻塞,直到反馈结果(有数据...

  • 从零开始netty学习笔记之BIO

    BIO即Block IO,阻塞式IO。网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相...

  • Java阻塞式IO通信

    阻塞式IO通信 一、BIO通信介绍 网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互...

  • BIO、NIO、AIO 个人总结

    BIO(blocking io) BIO即为阻塞IO,在网络编程中,它会在建立连接和等待连接的对端准备数据阶段进行...

  • NIO 学习

    1. BIO网络模型 缺点: 阻塞式I/O模型 弹性伸缩能力差 多线程耗资源 2. NIO网络模型 优点: 非阻塞...

  • 一张图解决NIO原理

    BIO 阻塞式IO BIO模型 我们可以看到BIO模型中有两处阻塞的地方,第一是socket一直等待请求的到来,第...

  • NIO,BIO,AIO

    BIO:BlockingIO,阻塞式的IO,简单的来说,BIO就是当发起IO的读写操作时,均为阻塞模式,只有当程序...

  • 网络模型

    网络模型 BIO(同步阻塞IO) 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式。 同步并阻塞,服务...

  • Java Socket 编程那些事(2)

    前言 在上一篇博客中,我们使用了BIO,也就是同步阻塞式IO实现了Socket通信。Java Socket编程那些...

网友评论

      本文标题:BIO阻塞式网络编程

      本文链接:https://www.haomeiwen.com/subject/kojszqtx.html