一、TCP和UDP有什么区别?TCP为什么是三次握手,而不是两次
TCP作为一种可靠传输控制协议,其核心思想既要保证数据可靠传输,又要提高传输的效率,而用三次恰恰可以满足以上两方面的需求!
TCP可靠传输的精髓:TCP连接的一方A,由操作系统动态随机选取一个32位长的序列号(Initial Sequence Number),假设A的初始序列号为1000,以该序列号为原点,对自己将要发送的每个字节的数据进行编号,1001,1002,1003…,把自己的初始序列号ISN告诉B,让B有一个思想准备,什么样编号的数据是合法的,什么编号是非法的,比如编号900就是非法的,同时B还可以对A每一个编号的字节数据进行确认。如果A收到B确认编号为2001,则意味着字节编号为1001-2000,共1000个字节已经安全到达。
同理B也是类似的操作,假设B的初始序列号ISN为2000,以该序列号为原点,同理B也是类似的操作,假设B的初始序列号ISN为2000,以该序列号为原点,以便A可以确认B发送的每一个字节。如果B收到A确认编号为4001,则意味着字节编号为2001-4000,共2000个字节已经安全到达。
一句话概括,TCP连接握手,握的是啥?
通信双方数据原点的序列号!
以此核心思想我们来分析二、三、四次握手的过程。
A <-------> B
四次握手的过程:
1.1 A 发送同步信号SYN A's Initial sequence number
1.2 B 确认收到A的同步信号,并记录 A's ISN 到本地,命名 B's ACK sequence number
1.3 B发送同步信号SYN B's Initial sequence number
1.4 A确认收到B的同步信号,并记录 B's ISN 到本地,命名 A's ACK sequence number
很显然1.2和1.3 这两个步骤可以合并,只需要三次握手,可以提高连接的速度与效率。
二次握手的过程:
2.1 A 发送同步信号SYN A's Initial sequence number
2.2 B发送同步信号SYN B's Initial sequence number B's ACK sequence number
这里有一个问题,A与B就A的初始序列号达成了一致,这里是1000。但是B无法知道A是否已经接收到自己的同步信号,如果这个同步信号丢失了,A和B就B的初始序列号将无法达成一致。
于是TCP的设计者将SYN这个同步标志位SYN设计成占用一个字节的编号(FIN标志位也是),既然是一个字节的数据,按照TCP对有数据的TCP segment 必须确认的原则,所以在这里A必须给B一个确认,以确认A已经接收到B的同步信号。
有童鞋会说,如果A发给B的确认丢了,该如何?
A会超时重传这个ACK吗?不会!TCP不会为没有数据的ACK超时重传。 那该如何是好?B如果没有收到A的ACK,会超时重传自己的SYN同步信号,一直到收到A的ACK为止。
流程:
第一个包,即A发给B的SYN 中途被丢,没有到达B
A会周期性超时重传,直到收到B的确认
第二个包,即B发给A的SYN ACK 中途被丢,没有到达A
B会周期性超时重传,直到收到A的确认
第三个包,即A发给B的ACK 中途被丢,没有到达B
A发完ACK,单方面认为TCP为 Established状态,而B显然认为TCP为Active状态
a. 假定此时双方都没有数据发送,B会周期性超时重传,直到收到A的确认,收到之后B的TCP 连接也为 Established状态,双向可以发包。
b. 假定此时A有数据发送,B收到A的 Data ACK,自然会切换为established 状态,并接受A的 Data。
c. 假定B有数据发送,数据发送不了,会一直周期性超时重传SYN ACK,直到收到A的确认才可以发送数据。
二、JAVA有哪几种IO模型?有什么区别?
BIO 同步阻塞IO:可靠性差,吞吐量低,使用于连接比较少且比较固定的场景。jdk1.4前只有这一种模型。编程模型最简单
NIO 同步非阻塞IO:可靠性比较好,吞吐量比较高,适用于连接比较多且连接比较短(轻操作)。(例如聊天室,每人发一句话)jdk1.4后支持。编程模型最复杂
AIO 非同步阻塞IO:可靠性是最好的,吞吐量高。适用于连接比较多且连接比较长(重操作)。(例如文件服务器)jdk1.7后支持的。编程模型比较简单,但是需要操作系统来进行异步通知
同步阻塞概念:
三、JAVA NIO的几个核心组件是什么?分别有什么作用?
Client会把数据写到Buffer当中,写会有一个写的事件,这个事件会通过Channel注册到Selector上,通知Selector,Selector再通知Server来安排空闲线程来处理
Channel类似于一个流,每个Channel对应一个Buffer缓冲区。Channel会注册到Selector。
Selector会根据Channel上发生的读写事件,将请求交由某个空闲线程处理,Selector对应一个或多个线程,线程数量由Server端控制
Buffer和Channel都是可读可写的
四、select,poll,epoll有什么区别
他们是NIO中多路复用的三种实现机制,是由Linux操作系统提供的
用户空间和内核空间:操作系统为了保护系统安全,将内核划分为两个部分,一个是用户空间,一个是内核空间,用户空间不能直接访问底层的硬件设备,必须通过内核空间。
文件描述符 File Descriptor(FD):是一个抽象的概念,形式上是一个整数,实际上是一个索引值。指向内核中为每个进程维护进程所打开的文件的记录表。当程序打开一个文件或创建一个文件时,内核就会向进程返回一个FD。通常只会在Unix,Linux系统。
select机制:会维护一个FD的集合 fd_set。实现多路复用是将fd_set从用户空间复制到内核空间,再激活socket连接,但是x64的操作系统下对fd_set的大小是有限制的,为2048
Poll机制:它的机制和select机制是差不多的,但是它将fd_set结构进行了优化,FD集合的大小就突破了操作系统的限制。fd_set是一个数组结构,在poll里使用了pollfd代替了fd_set,pollfd是通过链表实现的。
EPoll机制(Event Poll):Linux2.6提出来的,事件驱动,它不再扫描所有的FD,只将用户关心的FD的事件存放到内核的一个事件表。这样就可以减少用户空间与内核空间之前需要拷贝的数据。