服务端网络编程常见网络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