JAVA网络通信简析

\

一、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的事件存放到内核的一个事件表。这样就可以减少用户空间与内核空间之前需要拷贝的数据。

五、描述一下Http和Https的区别