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

人生之路坎坎坷坷,跌跌撞撞在所难免。但是,不论跌了多少次,你都必须坚强勇敢地站起来。任何时候,无论你面临着生命的何等困惑抑或经受着多少挫折,无论道路多艰难,希望变得如何渺茫,请你不要绝望,再试一次,坚持到底,成功终将属于勇不言败的你。

导读:本篇文章讲解 用java实现BIO服务端和客户端-Netty系列(一),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

服务端网络编程常见网络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()方法,关闭资源成功
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/133949.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!