目录
io
io和nio的区别
io是指io流,他实现了从磁盘中的读取和写入。内存,网络都可以作为io流的数据来源和目的地。Java提供字节流和字符流实现数据流的操作。当程序向网络进行数据操作时,使用socket方式实现数据网络传输。
基于socket的io通信属于阻塞式io,在连接及io事件未就绪的情况下,当前连接会处于阻塞状态,如果某个连接处理阻塞状态,那么后续连接都得等待。服务端能够处理的连接非常有限。
nio是一种新的io机制,nio在效率上做了优化,并且新增量3个核心组件:channel,Buffer,selectors。提供了非阻塞特性。对网络io来说,nio通常称为非阻塞io。
在通过nio进行网络数据传输时,在连接或io事件未就绪的情况下,服务器端不会阻塞当前连接,而是继续轮询后续连接并进行处理。所以在nio里面,服务器端能够处理的连接数量更多。
Java中有几种文件拷贝,哪种最高
io包下,fileInputStream,nio包下,transferTo,Files.copy
在文件的io操作中,我们使用操作系统底层标准io系统调用函数Read和Write,由于内核指令调用会使得当前用户线程切换到内核态,然后内核线程负责把相应的文件数据读取到内核io缓冲区里,接着把数据从内核io缓冲区拷贝到进程的私有地址空间里,这样完成了一次io操作。nio提供了transferTo和transferFrom方法,零拷贝实现,利用操作系统底层机制,避免不必要的拷贝和上下文切换,性能比较好。
io的多路复用机制
io多路复用是一种同步io模型,实现一个线程监视多个文件句柄。一旦某个文件句柄就绪,就通知对应的应用程序进行相应的读写操作,没有文件句柄的时候就会阻塞应用程序,从而释放CPU资源。
io可以理解为,操作系统里,数据在用户态和内核态之间的读写操作,大部分情况下是指网络io,多路大部分情况下指多个tcp连接,也就是多个socket或多个channel,复用指的是复用一个或多个线程资源。io多路复用的意思是,一个或多个线程处理多个tcp连接,尽可能减少系统开销,无须创建和维护过多进程和线程。
io多路复用模型
select模型:基本原理是采用轮询和遍历的方式实现,客户端操作服务器的时候,系统创建文件描述符,FD,常见的文件描述符有writefds写描述符,readfds读描述符,exceptfds异常描述符。select模型会阻塞监视文件描述符,在有数据可读,可写、异常或者超时都会返回,返回后遍历文件描述符集合,找到为就绪的FD,然后触发相应的io操作。优点:跨平台支持好。缺点:select模式采用轮询的方式全盘扫描,随着FD增大而性能下降。每次调用select方法,都需要把FD集合从用户态拷贝到内核态,进行遍历。而操作系统对于单个进程打开的FD数量是有限,默认1024.虽然可以FD_SETSIZE修改,但是,在io吞吐量巨大的时候,效率提升有限。
poll模型:与select模型基本一致,采用轮询加遍历实现,采用了链表方式存储FD。优点:没有最大FD的限制。缺点:采用轮询的方式全盘扫描,会随着FD数量增大导致性能下降。
epoll模型:采用事件通知机制触发相应的io操作。没有FD个数限制,而且从用户态拷贝到内核态只需要一次。他主要通过系统底层函数注册、激活FD,触发相关的io操作,这大大提高了性能。epoll_create函数。在系统启动时,该函数在Linux内核中申请一个B+树结构的文件系统,然后返回epoll对象,即一个FD。
epoll_ctl函数,每新建一个连接的时候,会同步更新epoll对象中的FD,并绑定一个回调函数。epoll_wait函数,轮询所有的回调函数集合,并触发对应的io操作。
因此,epoll模型的优点是将轮询改成了回调,提高了CPU执行效率,不会随着FD数量增加导致性能下降。他能支持的FD数量上限是操作系统的最大文件句柄数。缺点:只能在Linux下工作。
网络编程
网络四元组
IP地址、端口号,源、目标。四元组的设计原理:当一个客户端和服务器建立一个TCP连接的时候,通过四元组确定一个唯一的TCP连接。TCP是全双工协议,允许数据在连接的2个方向上同时传输。
TCP为什么要设计3次握手
目的是确保通信双方都具备发送和接受数据的能力,从而建立一个可靠的连接。
tcp是一种可靠的,基于字节流的,面向连接的传输层双工协议。
3个特征:
1.通信双方的数据传输是稳定的,保证数据传输到目标端口。
2.TCP通信双方的数据包传输通过字节流实现。
3.数据传输之前,必须建立一个连接,然后基于这个连接进行数据传输。
因为TCP在进行数据通信之前需要建立一个可靠的连接。所以TCP采用了3次握手的方式来建立连接。3次握手,就是通信双方一共需要发送3次请求,才能确保这个连接的建立,
流程:1.客户端向服务器端发送连接请求并携带同步序列号SYN seq=x。
2.服务器端收到请求后,发送SYN=y和ACK=x+1,这里SYN表示服务端的同步序列号,ACK表示对前面收到的请求的确认,告诉客户端,请求已经收到。
3.客户端收到服务器的请求后,再次发送ACK=y+1,这个ACK是对服务端的连接确认,告诉服务端请求已经收到。
3次握手原因:
1.TCP 是可靠通信协议,所以通信双方都必须维护1个序列号,用来标记已经发送的数据包里哪些是已经被对方签收的。3次握手就是通信双方相互告知序列号的起始值,为了确保这个序列号被收到,双方都需要有确认操作。
2.TCP需要再一个不可靠的环境下实现可靠的数据传输,意味着通信双方必须实现一个可靠的数据传输通道,而3次通信是建立这样一个通道的最小通信次数。
3.防止历史的重复连接问题,例如在网络比较差的环境下,客户端连续多次发送连接请求。假设只有2次握手,那么服务器端只能接受或拒绝这个请求。但是服务端不知道这次请求是不是之前因为网络堵塞而过期的请求,服务端不知道这个请求是有效还是无效。
cookie和session
cookie:客户端浏览器用来保存服务端数据的一种机制,当通过浏览器访问页面时候,服务端可以把某些状态数据通过键值对的方式写入cookie中并存储到客户端浏览器上。客户端下一次访问服务端的时候,就可以携带这些状态数据发送到服务端,服务器就可以根据cookie携带的内容来识别使用者。
session:表示一个会话,他属于服务端的容器对象。在默认情况下,针对每一个浏览器请求,servlet容器会分配一个session。session本质上是一个hashmap,可以存储当前会话产生的状态数据。
http是一个无状态的协议,服务端不知道客户端发送过来的多次请求是属于同一个用户。session可以弥补http无状态的不足。服务端可以使用session来存储客户端在同一个会话中的多次请求记录。session和cookie实现有状态的http。
工作原理:客户端第一次访问服务端的时候,服务端会针对这次请求创建一个会话,并生成一个唯一的sessionid来标记这个会话。然后服务端把这个sessionid写入客户端浏览器的cookie里,用来实现客户端状态的保存。在后面的请求里,每次都会携带sessionid,服务端根据这个sessionid来识别当前会话状态。