文章目录
一、Socket
- Socket读缓冲和写缓冲
- 阻塞和非阻塞
- Socket API简单使用
二、I/O多路复用
什么是I/O多路复用?
文件描述符fd
select函数
select函数接口
select具体工作流程
epoll讲解
- 基本原理
- epoll优点
- epoll接口
- epoll_create函数
- epoll_ctl 函数
- epoll_wait函数
一、Socket
在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。
Socket读缓冲和写缓冲
平时用的socket(套接字)只是一个引用,这个socket对象实际上是放在操作系统内核中。socket内部有两个重要的缓冲结构,一个是读缓冲,一个是写缓冲,读写缓冲都是有限大小的数组结构。
当我们对客户端的socket写入字节数组时,是将字节数组拷贝到内核区socket的write buffer中,内核网络模块会有单独的线程负责不停地将write buffer的数据拷贝到网卡硬件,网卡硬件再将数据送到网线,经过一些列路由器交换机,最终送达服务器的网卡硬件中。
同样,服务器内核的网络模块也会有单独的线程不停地将收到的数据拷贝到socket的read buffer中等待用户层来读取。最终服务器的用户进程通过socket引用的read方法将read buffer中的数据拷贝到用户程序内存中进行反序列化成请求对象进行处理。然后服务器将处理后的响应对象走一个相反的流程发送给客户端。
阻塞和非阻塞
socket读写也是分阻塞和非阻塞
因为write buffer空间都是有限的,所以当write buffer 满了,写操作就会阻塞,直到空间被腾出来。当有了NIO(非阻塞IO),写操作也可以不阻塞,假设write buffer空间还剩1M,此时一个客户端请求写数据是2M,那么就会先写进去1M,然后返回客户端,告知写进去多少,还剩1M没有写进去的内容用户进程会缓存起来,后续会继续重试写入。
读操作也是一样,read buffer的内容可能会是空的。这样socket的读操作也会阻塞,直到read buffer中有了足够的内容才会返回。有了NIO,就可以有多少读多少,不会阻塞。
Socket API简单使用
客户端简单实例代码
public class TCPClient { public static void main(String[] args) throws IOException { Socket s=new Socket("127.0.0.1",6666); OutputStream os=s.getOutputStream(); //将数据写入到socket DataOutputStream dos=new DataOutputStream(os); dos.writeUTF("Hello,server!"); //读取从服务端传回来的数据 DataInputStream dis=new DataInputStream(s.getInputStream()); System.out.println(dis.readUTF()); }}
服务端简单实例代码
/** * Socket服务端Demo */public class TCPServerDemo { public static void main(String[]