网络编程基础
网络编程API---socket
传输层和应用层分别基于TCP和IP协议,通过操作系统内核和内核协议栈控制操作,而应用层业务程序想要操作需要通过socket调用操作系统内核向外暴露的API。
网络IO的操作
客户端和服务端建立链接通过TCP协议,链接建立跟应用程序没关系,通过系统内核建立,链接建立后将链接数据放入操作系统内核缓存区(链接队列),应用层程序通过api与缓存进行数据交互
什么是IO?
用户空间就是jvm,也是一个进程
同步/异步、阻塞/非阻塞
在I/O操作中有这么I两组概念,其中同步/异步要和线程中的同步线程/异步线程要区分开,这里指的是同步IO/异步IOIO
阻塞/非阻塞:没有数据传过来时,读会阻塞直到有数据;缓冲区满时,写操作也会阻塞。
非阻塞遇到这些情况,都是直接返回(要做应用轮询)。
同步/异步:数据就绪后需要自己去读是同步,数据就绪后系统直接读好再回调给程序是异步。
操作系统提供的IO模型
同步阻塞IO

同步非阻塞IO

IO多路复用
使用select检测哪些socket有数据,对有数据的socket进行读操作,避免了阻塞
信号IO
异步IO
读数据时,没有数据会直接返回并注册一个回调函数,当有数据时调用回调。
BIO模型
服务端ServerSocket接收一个socket,代表客户端的链接,分配一个线程处理客户端发送过来的数据
代码示例
package com.example.bio;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;public class BioClient {public static void main(String[] args) {Socket socket = null;BufferedReader in = null;BufferedWriter out = null;try {socket = new Socket("127.0.0.1", 8888);in = new BufferedReader(new InputStreamReader(socket.getInputStream()));out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));System.out.println("准备向服务端写数据!");//向服务端发送数据out.write("我是客户端,我向服务端发送了数据!\n");out.flush();//接收来自服务端的数据String line = in.readLine();System.out.println("收到来自服务端的数据:" + line);} catch (Exception e) {if (in != null) {try {in.close();} catch (Exception e1) {e1.printStackTrace();}}if (out != null) {try {out.close();} catch (Exception e1) {e1.printStackTrace();}}if (socket != null) {try {socket.close();} catch (Exception e1) {e1.printStackTrace();}}}}
}
package com.example;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class BioServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8888);System.out.println("服务端绑定接口。开启监听");while (true) {Socket socket = serverSocket.accept();System.out.println("有客户端连接了,socket=" + socket);new Thread(new ServerHandler(socket)).start();}}static class ServerHandler implements Runnable {private Socket socket;public ServerHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {//负责读写数据,业务操作InputStream inputStream = socket.getInputStream();//服务端从客户端读取数据OutputStream outputStream = socket.getOutputStream();//服务端向客户端写数据BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));while (true) {String line = reader.readLine();System.out.println("收到来自客户端的数据:" + line);//向客户端写数据writer.write("服务端收到数据,hello,client! \n");writer.flush();}} catch (Exception e) {e.printStackTrace();}}}
}
NIO模型
底层不是单纯的同步非阻塞,而是I/O多路复用(也是非阻塞的,多了检测机制)。