深入浅出IO模型(一):BIO
目录
预备阶段
首先,我们编写一个简单的socket程序
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class jooks {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(8090); //主动套接字 => 监听套接字
System.out.println("new a socket on port:8090");
while (true) {
Socket client = socket.accept(); //监听套接字 => 已连接套接字
System.out.println("client\t" + client.getPort());
new Thread(() -> {
try {
InputStream is = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
while (true) {
System.out.println(reader.readLine()); //recv
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
通过strace -ff -o ./ooxx java jooks
抓取运行这个java程序产生的系统调用
然后可以在当前文件目录下发现很多文件
这些ooxx.*就代表一个个线程被记录的系统调用。(启动jvm就会产生很多线程)
这时候通过grep 'port:8090' ./*
查找我们java程序中写的输出。
发现在1865中。打开ooxx.1865文件发现如下内容。
通过jps
命令查看java进程的id号。
然后进入/proc/1864/fd
发现这里有如下文件,0-5分别对应了ooxx文件中的数字(文件描述符)。其中最后两个是socket。
开始通信
这时通过nc 127.0.0.1 8090
与java进程产生通信
这时候,多了一个ooxx文件
等会儿再进去,先去看看ooxx.1865线程发生了什么变化
可以看到这里accept了127.0.0.1:42556的连接。同时,/proc/1864/fd也发生了变化
发现这里多了一个叫6的socket,这就是ooxx.1865中看到的accpet返回的。
我们再看看新产生的ooxx.1906。
发现这里有个recvfrom,然后还write了我们nc发送的数据,这时候nc再发一行试试。
至此实操结束。
做个小总结
刚刚发生了什么,如下图所示。
创建主动套接字4
根据4创建监听套接字5
绑定8090端口、设置监听
调用poll() ===========> 客户端发送连接,服务端accpet(),然后返回已连接套接字6
从6,recv(阻塞式)
画个图
可以发现,这种模式处理多个客户端请求时,是产生多个线程来应付的,产生的系统调用也很多,不是一个好办法。
以上就是bio模型