用java实现BIO服务端和客户端-Netty系列(一)

服务端网络编程常见网络IO模型

作为 Java Web 程序员,你有想过 Web 服务器(Nginx,Tomcat,Jetty等)是如何接受你的 HTTP 请求的吗?你知道 其实 HTTP 也是基于 TCP/IP 的文本协议吗?

根据应用进程系统调用方式的阻塞、非阻塞,操作系统在处理应用程序请求时处理方式的同步、异步处理的不同,参考权威:RFC标准,或者书籍 《UNIX Network Programming》中文名《UNIX网络编程-卷一》第六章:
1)阻塞式I/O(blocking IO);
2)非阻塞式I/O(nonblocking IO);
3)I/O复用(select,poll,epoll…)(IO multiplexing);
I/O多路复用是阻塞在select,epoll这样的系统调用,没有阻塞在真正的I/O系统调用如recvfrom
进程受阻于select,等待可能多个套接口中的任一个变为可读
IO多路复用使用两个系统调用(select和recvfrom)
blocking IO只调用了一个系统调用(recvfrom)
select/epoll 核心是可以同时处理多个connection,而不是更快,所以连接数不高的话,性能不一定比多线程+阻塞IO好
多路复用模型中,每一个socket,设置为non-blocking,
阻塞是被select这
4)信号驱动式I/O(signal-driven IO);
5)异步I/O(asynchronous IO) Future-Listener机制;

什么是阻塞/非阻塞 同/异步

洗衣机洗衣服
洗衣机洗衣服(无论阻塞式IO还是非阻塞式IO,都是同步IO模型)
同步阻塞:你把衣服丢到洗衣机洗,然后看着洗衣机洗完,洗好后再去晾衣服(你就干等,啥都不做,阻塞在那边)
同步非阻塞:你把衣服丢到洗衣机洗,然后会客厅做其他事情,定时去阳台看洗衣机是不是洗完了,洗好后再去晾衣服(等待期间你可以做其他事情,比如用电脑打开小D课堂看视频学习)
异步阻塞: 你把衣服丢到洗衣机洗,然后看着洗衣机洗完,洗好后再去晾衣服(几乎没这个情况,几乎没这个说法,可以忽略)
异步非阻塞:你把衣服丢到洗衣机洗,然后会客厅做其他事情,洗衣机洗好后会自动去晾衣服,晾完成后放个音乐告诉你洗好衣服并晾好了

在Java中,提供了一些列API,可以供开发者来读写外部数据或文件。我们称这些API为Java IO。
IO是Java中比较重要,且比较难的知识点,主要是因为随着Java的发展,目前有三种IO共存。分别是BIO、NIO和AIO。

java BIO

BIO 全称Block-IO 是一种同步且阻塞的通信模式。是一个比较传统的通信方式,模式简单,使用方便。但并发处理能力低,通信耗时,依赖网速。

Java NIO

Java NIO,全程 Non-Block IO ,是Java SE 1.4版以后,针对网络传输效能优化的新功能。是一种非阻塞同步的通信模式。
NIO 与原来的 I/O 有同样的作用和目的, 他们之间最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。
面向流的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。
面向块的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。

Java AIO

Java AIO,全程 Asynchronous IO,是异步非阻塞的IO。是一种非阻塞异步的通信模式。
在NIO的基础上引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

简单实现BIO服务端

import java.net.ServerSocket;
import java.net.Socket;

public class BioServer {

    private static final int PORT = 8080;

    public static void main(String[] args){
        try(ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("服务端启动~");
            Socket socket = null;
            while (true) {
                socket = serverSocket.accept();
                new Thread(new BioServerHandler(socket)).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
import java.io.*;
import java.net.Socket;

public class BioServerHandler implements Runnable {

    private Socket socket;

    public BioServerHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try(BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
            Socket socket = this.socket ) {
            String msg = null;
            while ((msg = in.readLine()) != null && msg.length() != 0) {
                System.out.println("服务端接收到的值" + msg);
                out.println("aaaaaaaaaa");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

cmd 使用 telnet 测试
telnet localhost 8080

在这里插入图片描述
在这里插入图片描述

JDK7及以后关闭资源的正确姿势
try-with-resource Resource的定义:
所有实现了 java.lang.AutoCloseable[1] 接口(其中,它包括实现了 java.io.Closeable[2] 的所有对象),可以使用作为资源。
在这里插入图片描述
在 java.net.Socket close() 方法上打断点,debug运行
关闭客户端时,进入close()方法,关闭资源成功
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值