大纲
1.网络基础的相关问题总结
2.七层模型和四层模型
3.物理层(网线 + 光缆 + 01电信号)
4.数据链路层(以太网协议 + 网卡mac地址)
5.网络层(IP协议 + 子网划分 + 路由器)
6.传输层(TCP和UDP协议 + Socket + 端口)
7.应用层(HTTP协议 + SMTP协议)
8.浏览器请求一个域名会发生什么
9.TCP三次握手建立连接的过程
10.如果TCP建立连接只握手两次
11.TCP断开连接的四次挥手
12.Socket编程和TCP/IP协议的关系
13.HTTP的工作原理
14.HTTPS的实现原理
15.全双工和半双工
16.Java进行IO读写的底层流程
17.同步和异步 + 阻塞和非阻塞
18.Linux的常用IO模型
19.IO多路复用技术
20.select、poll、epoll的区别
1.网络基础的相关问题总结
首先是七层模型和四层模型,然后是一次请求的全过程,接着是传输层的TCP连接(三次握手和四次挥手),然后就是传输层TCP协议上的Socket编程,最后是应用层的HTTP协议。
2.七层模型和四层模型
TCP/IP四层模型(应传网数):应用层、传输层、网络层、数据链路层。其中每一层对应的协议分别是:数据链路层(以太网协议),网络层(IP协议),传输层(TCP协议),应用层(HTTP协议)。
OSI七层模型(应表会传网数物):应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。注意:物理层(网线和光缆传递01电信号),会话层、表示层、应用层 -> 应用层。
电脑的网络设置中一般会包含IP地址、子网掩码、网关地址、DNS地址。IP地址和子网掩码用来划分子网,判断哪些IP地址在一个子网内。IP地址和mac地址是关联起来的,可以唯一定位网卡。网关地址可以认为是路由器上的那个网卡的IP地址,路由器上的网卡也有mac地址,mac地址对应了一个IP地址。
3.物理层(网线 + 光缆 + 01电信号)
物理层指的是通过网线或光缆把各个电脑连接起来形成一个网络。物理层负责传输0和1的电信号,计算机的最底层就是0和1的电信号,所以物理层通过传输0和1的电信号把各个电脑连接起来。
4.数据链路层(以太网协议 + 网卡mac地址)
数据链路层负责处理0和1的电信号如何分组,比如在一连串的电信号中区分哪些0和1分为一组、对应什么意思。一组电信号是一个数据包,也叫一个帧(frame)。每个帧分成两个部分,标头(head)和数据(data)。标头是一些说明性的数据,比如发送者、接收者和数据类型等。
//比如定义:
00000011(从电脑1出发,要到电脑2去)
00101(从电脑1出发,要到电脑3去)
0101(从电脑2触发,要到电脑4去)
01(从电脑3出发,要到电脑5去)
以太网协议规定了电信号的分组方式,在其协议下发送的数据包必须指定目标电脑网卡的mac地址。以太网协议规定了接入网络的所有设备都要有个网卡,每个网卡必须包含一个mac地址,mac地址就是网卡的唯一标识。所以以太网协议里的数据包,或者说在数据链路层传输的数据包,必须从一台电脑的网卡传输到另外一台电脑的网卡。
在以太网里面,如果一台电脑发送一个数据包出去,会广播给局域网(子网)内的所有电脑的网卡,然后每台电脑都从数据包里获取接收者的mac地址,跟自己的mac地址进行对比,如果一样就说明这是发给自己的数据包。
5.网络层(IP协议 + 子网划分 + 路由器)
(1)IP协议区分电脑属于哪个子网
(2)两个IP地址是否属于一个子网
(3)两台电脑如何传输数据包
(4)路由器的作用
(5)交换机和路由器的对比
(6)两个局域网如何通过路由器通信
(7)总结
(1)IP协议区分电脑属于哪个子网
子网(局域网)内的电脑在以太网协议下,是通过广播方式将一个数据包发送给另一台电脑的。
但是如何知道哪些电脑是在同一个子网内的呢?网络层里有IP协议,通过IP协议就可以区分哪些电脑是一个子网的。
(2)两个IP地址是否属于一个子网
每台计算机都会分配一个IP地址,如IPV4版本的IP地址由32个二进制数字组成。其中前24位代表了网络,后8位代表了主机。
如果要判断两个IP地址是否是一个子网的,则要分别把两个IP地址和自己的子网掩码进行二进制的位与运算,位与运算后再比较一下代表网络的那部分,如果网络的那部分是一样的才是一个子网。
(3)两台电脑如何传输数据包
两台在子网内的电脑可以通过广播 + mac地址的判断来发传输据包,两台不在子网内的电脑则不能通过广播而需要通过路由器来传输数据包。
(4)路由器的作用
路由器负责将多个子网(局域网)进行连接。家里的网络是一个子网,要访问的网站是另一个子网。
路由器其实就是配置了多个网卡的一个专用设备,可以通过不同的网卡接入不同的子网。
路由器上的每个网卡都有mac地址和对应的IP地址。路由器虽然有mac地址,但是不能通过mac地址寻址。必须通过IP地址寻址,所以路由器是工作在网络层的设备。
(5)交换机和路由器的对比
交换机主要用在局域网(子网)的通信,局域网里的电脑就是通过交换机把数据包广播到局域网内的其他电脑上。
交换机是通过mac地址来寻址和传输数据包的,基于以太网协议工作在数据链路层。路由器是通过IP地址来寻址和传输数据包的,基于IP协议工作在网络层。网关也是路由器的一种,工作在网络层。
LAN就是Local Area Network(局域网),WAN就是Wide Area Network(广域网),WLAN就是Wireless Local Area Network(无线局域网WIFI)。
(6)两个局域网如何通过路由器通信
步骤一:首先路由器1配置了两块网卡分别和两个局域网相连。
步骤二:然后子网1的电脑先通过交换机将数据包发送给路由器1。该过程要将路由器1的一块网卡的IP地址所对应的mac地址写到数据包头部,然后才能通过交换机将数据包广播出去到路由器1。
步骤三:接着路由器1通过IP地址寻址后把数据包传输到路由器2。
步骤四:当路由器2接收到数据包后会比较自己网卡里的mac地址确认是否给自己,然后会在子网2内将目标机器的IP地址对应的mac地址写入数据包头部,接着再次通过交换机广播给子网2的目标电脑。
一个局域网内的每台机器都有自己的ARP缓存,ARP的作用是用来在一个局域网内让各个设备知道彼此的IP地址和mac地址的。
一个IP地址对应着一个mac地址。如果子网内的机器需要进行通信,只需在数据包写上对方的mac地址,再通过交换机广播到对方的机器上即可。如果跨子网的机器需要进行通信,就要在数据包写上对方的IP地址,然后先通过mac地址广播到路由器,接着路由器再把数据包传输到路由器,最后让路由器再根据另外一个子网的IP地址转换为mac地址,然后通过另外一个子网的交换机广播到对方的机器上。
(7)总结
网络层最重要的协议就是IP协议,IP协议定义了一个个的IP地址,通过IP地址可以划分出一个个的子网。
子网内通信是通过以太网协议 + mac地址 + 交换机来广播数据包的。
跨子网通信是先通过交换机将数据包广播到路由器(网关)上去,路由器(网关)可能会再进行不断转发到另一个路由器(网关),直至转发到最后一个路由器发现目标机器的IP地址和自己是在同一个子网内,最后一个路由器根据ARP缓存可以知道目标机器的IP地址和对应子网的mac地址。所以由最后一个路由器通过以太网协议 + mac地址 + 交换机,把数据包广播到目标机器的网卡上。
跨子网通信:IP地址 -> mac地址 -> 交换机 -> 路由器 -> IP地址 -> 交换机。
6.传输层(TCP和UDP协议 + Socket + 端口)
网络层基于IP协议,可实现一个主机到另一个主机的寻址和通信。
传输层基于TCP/UDP协议,可实现一个主机端口到另一个主机端口的连接和通信,这个通信就是通过Socket来实现的。
通过Socket可以基于TCP/IP协议完成基于IP地址和mac地址的转换和寻址,然后通过路由器通信建立一个端口到另外一个端口的连接。
UDP和TCP都是传输层的协议,作用就是在数据包里加入端口号,这样就可以通过端口号进行点对点的通信。UDP协议是不可靠的,发出去的数据不确定是否能收到。TCP协议是可靠的,要进行三次握手,收到数据必须要进行回复。
7.应用层(HTTP协议 + SMTP协议)
通过传输层的TCP协议可以实现应用间的数据传输,而不同的应用如邮件、网页等都会定义不同的应用层协议。常见的应用层协议有HTTP协议、SMTP协议等,这里的应用层综合了会话层、表示层、应用层。
8.浏览器请求一个域名会发生什么
整体过程:
首先根据域名去找DNS服务器获取其对应的IP地址,接着用子网掩码去判断本地IP地址和域名IP地址是否在同一个子网。如果在同一个子网,则根据以太网协议 + mac地址 + 交换机将数据包广播出去。如果不在同一个子网,则先将数据包发送给网关(路由器),再由网关转发数据包给域名IP所在子网的网关。
应传网数:
应用层(HTTP协议)-> 传输层(TCP协议) -> 网络层(IP协议) -> 数据链路层(以太网协议)。
步骤一:
浏览器请求一个域名,先按照应用层的HTTP协议,将HTTP请求报文封装成一个HTTP数据包,此时的HTTP数据包是没有头的。
步骤二:
接着HTTP数据包来到传输层,该层的TCP协议会HTTP给数据包设置端口。也就是会把HTTP数据包封装到一个TCP数据包上,并且添加一个TCP头,这个TCP头会包含发送者和接收者的端口。
步骤三:
接着TCP数据包来到网络层,该层的IP协议会给TCP数据包设置IP地址。也就是会把TCP头和TCP数据包封装到一个IP数据包里,并且添加一个IP头,这个IP头里会包含发送者和接收者的IP地址。通过IP协议,可以判断发送者和接收者的IP地址是否是在同一个子网的。
步骤四:
接着IP数据包来到数据链路层,该层的以太网协议会给IP数据包设置mac地址。也就是把IP头和IP数据包封装到一个以太网数据包里,并且添加一个以太网头。这个以太网头里会包含发送者和接收者的网卡的mac地址,以太网数据包的大小限制是1500字节。
步骤五:
以太网数据包会通过交换机被发送到网关(路由器),网关(路由器)又会将数据包发送给别的子网,最后到达服务器接收者。
9.TCP三次握手建立连接的过程
在Socket编程中,三次握手的过程会由客户端执行connect()方法来触发。
第一次握手:
客户端发送连接请求报文:ACK = 0、SYN = 1、seq = x。当客户端发出连接请求报文后,会处于SYN_SENT状态,等待服务器的响应。
第二次握手:
服务端收到SYN = 1的连接请求报文后,需要返回一个确认报文:ACK = 1、SYN=1、ack = x + 1、seq = y。当服务端发出确认报文后,会处于SYN_RECV状态。
第三次握手:
客户端收到ack = x + 1的确认报文后,会继续发送一个确认报文:ACK = 1、ack = y + 1、seq = x + 1。当服务端收到ack = y + 1的报文后,则说明连接建立成功,此时客户端和服务端都进入ESTABLISHED状态。
三次握手就是三次请求,所以每次握手都会进行:封装TCP数据包、封装IP数据包、封装以太网数据包,然后通过"IP地址 -> mac地址 -> 交换机 -> 路由器 -> IP地址 -> mac地址 -> 交换机"的方式进行数据传输。
10.如果TCP建立连接只握手两次
一.假如只需要两次握手就可以建立连接
如果客户端第一次握手发送过去,结果卡在某个地方没及时到达服务端。那么客户端会再次重试发送第一次握手过去,然后服务端收到了重发的第一次握手,于是返回第二次握手建立了连接。
当客户端和服务端完成通信后,原来卡在某个地方的第一次握手发到了服务端,于是服务端又返回一个第二次握手,并且开辟资源准备和客户端进行通信。
但是客户端此时已经通信完成了,不会再发送数据给服务端,从而造成服务端无效地开辟资源。
二.假如需要三次握手才可以建立连接
此时面对上述情况,客户端收到服务端延迟的第二次握手时就会发现不对,于是就可借助第三次握手发送复位报文告诉服务端撤销开辟的资源。此外由于3次握手就够了,所以不需要4次或5次浪费资源了。
11.TCP断开连接的四次挥手
第一次挥手:
客户端发送连接释放报文:FIN=1、seq=u,然后进入FIN-WAIT-1状态。
第二次挥手:
服务端收到报文后进入CLOSE_WATI状态,然后返回客户端一个确认报文:ACK=1、ack=u+1、seq=v。客户端收到确认报文后进入FIN-WAIT-2状态,此时从客户端到服务端的连接就释放了。
第三次挥手:
服务端发送连接释放报文:FIN=1、ack=u+1、seq=w,然后进入LAST-ACK状态。其中序列号seq是w而不是v+1,是因为服务端很可能又发送了一些数据。
第四次挥手:
客户端收到连接释放报文后,发送应答报文:ACK=1、ack=w+1、seq=u+1。然后进入TIME_WAIT状态,再等一会便会进入CLOSED状态,服务端收到应答报文后也会进入CLOSED状态。
由于TCP连接是全双工的,因此每个方向都必须要单独进行关闭。当一方完成数据发送任务后,需要发送一个FIN来终止这一方向的连接。收到一个FIN只是意味着这一方向上没有数据流动了也就是不会再收到数据,但在这个TCP连接上仍然可能会发送数据除非也发送一个FIN回去。
12.Socket编程和TCP/IP协议的关系
(1)Socket通信的原理
首先服务端会有一个ServerSocket无限等待客户端来进行连接。然后某个客户端如果要跟服务端连接,就需要在客户端本地创建一个Socket去连接服务端。接着建立连接后,服务端上的ServerSocket也会创建出一个Socket,这样就可以由客户端的Socket跟服务端的Socket进行通信。
其中连接的建立和释放,都是基于TCP三次握手和四次挥手来实现的。其中数据的传输是基于TCP协议的:封装TCP数据包 + TCP头(端口) -> 封装IP数据包 + IP头(IP地址) -> 封装以太网数据包 + 以太网头(mac地址)。
(2)Socket编程的核心方法
TCP服务端:socket() -> bind() -> listen() -> accept() -> read() -> write() -> close()。
TCP客户端:socket() -> connect() -> write() -> read() -> close()。
13.HTTP的工作原理
(1)请求报文和响应报文的结构
请求报文的结构:请求行(方法 + 地址 + 版本)、请求头、请求体。
响应报文的结构:响应行(版本 + 状态码 + 原因)、响应头、响应体。
(2)HTTP工作原理
经过TCP三次握手建立TCP连接后,会先将HTTP请求封装到应用层数据包,再封装到TCP数据包,再封装到IP数据包,最后封装到以太网数据包。
如果以太网数据包过大,那么会拆成几个包,然后通过以太网协议 + mac地址 + 交换机将数据包广播到网关(路由器)上。
以太网数据包来到网关后,又会经过多个网关进行转发,最后到达目标机器。接着通过一层层拆包获取到HTTP请求报文,交给应用程序进行处理。
最后目标机器会将HTTP响应按原路径返回给客户端,之后经过TCP四次挥手断开TCP连接。
(3)HTTP 1.0
默认是短连接,也就是底层的TCP连接是短连接。比如一个网页要向服务端发送30个请求,则要进行30次TCP连接的建立和释放。
(4)HTTP 1.1
默认是长连接,也就是底层的TCP连接是长连接。比如浏览器打开一个网页后,底层的TCP连接就保持着,不会马上断开。后续该网页发送的这30个请求就会共用一个TCP连接。
HTTP本身其实是没有所谓的长连接和短连接之说,HTTP是长连接还是短连接指的是,底层的TCP连接是长连接还是短连接。
HTTP服务一般用短连接,请求量大但每个请求不会频繁操作一般用短连接。数据库的连接一般用长连接,连接池一般使用的也都是长连接,而Dubbo://协议是基于长连接的。
14.HTTPS的实现原理
HTTPS的工作原理会在TCP连接3次握手的基础上附加一些信息。
步骤一:客户端把支持的加密规则发送给服务端。
步骤二:服务端从这套加密规则里选出一套加密算法和Hash算法,然后把自己的身份信息用证书的方式发给客户端,证书里会有服务端的地址、加密公钥、证书颁发机构。
步骤三:客户端收到消息后会验证证书的合法性,然后会生成一串随机数密码,并用证书里的公钥进行非对称加密,接着使用约定好的Hash算法生成握手消息的Hash值,然后用随机密码对消息进行对称加密,最后把加密数据、加密后的随机密码、Hash值发给服务端。
步骤四:服务端收到消息后会从中取出公钥加密后的随机密码,然后用本地的私钥对公钥加密后的随机密码进行解密取出随机密码。接着用随机密码解密客户端发来的握手消息,然后计算握手消息的Hash值并验证是否与客户端发过来的Hash值一致,最后用随机密码加密一段握手消息发给客户端。
步骤五:客户端拿到消息后,解密握手消息,然后计算消息的Hash值。如果计算的Hash值与服务端发来的Hash值一样,则握手结束。之后所有的数据都会由之前生成的随机密码,通过对称加密来加密。
非对称加密:加密的时候是用了一个公钥去加密,然后解密的时候是用私钥去解密。
对称加密:加密的时候用的算法,跟解密的时候用的算法是一样的。
常用的非对称加密算法是RSA算法,常用的对称加密算法是AES、RC4等,常用的Hash加密算法就是MD5。
15.全双工和半双工
全双工和半双工主要发生在交换机层面的。
如果是全双工,发送数据和接收数据可以同时进行。如果是半双工,同一时刻要么只能发送数据、要么只能接收数据。
使用半双工,需要先判断是否有数据正在接入,避免出现信号碰撞。使用全双工,不需要处理信号碰撞的问题,直接发送数据出去即可。
16.Java进行IO读写的底层流程
用户程序进行IO读写,基本上会用到系统调用read和write。系统调用read把数据从内核缓冲区(内核空间)复制到进程缓冲区(用户空间),系统调用write把数据从用户缓冲区(用户空间)复制到内核缓冲区(内核空间)。它们并不等价数据在内核缓冲区和磁盘之间的交换。
Java服务端处理网络请求的典型过程:
步骤一:接收客户端请求
Linux通过网卡,读取客户断的请求数据,将数据读取到内核缓冲区。
步骤二:获取请求数据
服务端从内核缓冲区读取数据到Java进程缓冲区。
步骤三:服务器端业务处理
Java服务端在自己的用户空间中处理客户端请求。
步骤四:服务器端返回数据
Java服务端已构建好的响应,从Java进程缓冲区写入内核缓冲区。
步骤五:发送数据给客户端
Linux内核通过网络IO ,将内核缓冲区中的数据,写入网卡。网卡通过底层的通讯协议,会将数据发送给目标客户端。
17.同步和异步 + 阻塞和非阻塞
同步和异步关注的是:是否亲自等消息、是否由其他线程告知自己。阻塞和非阻塞关注的是:当前事情还没做好时,是否还能做其他事情。
同步阻塞:事情没做好时,亲自等该事情做好的消息,且不做其他事情。
同步非阻塞:事情没做好时,会做其他事情,但会经常亲自等消息,轮询该事情是否做好。
异步阻塞:事情没做好时,不会做其他事情,但也不会亲自等消息,而是由其他线程告知。
异步非阻塞:事情没做好时,会做其他事情,也不会亲自等消息,而是由其他线程告知。
18.Linux的常用IO模型
一.阻塞IO模型
进程(用户线程)会在用户空间中执行recvfrom系统调用,recvfrom会一直等待直到数据已经从内核空间的内核缓冲区复制到用户空间的用户缓冲区或者发生错误时才返回。
所以进程(用户线程)从执行recvfrom系统调用开始,到recvfrom系统调用返回数据的这段时间内,都是阻塞的。
优点:程序简单,用户线程不会占用CPU资源。
缺点:一条线程维护一个连接,不适合高并发。
二.非阻塞IO模型
进程(用户线程)会在用户空间中执行recvfrom系统调用,如果用户空间的用户缓冲区没有数据,那么recvfrom就不要等了,而是直接返回一个错误,从而不阻塞进程(用户线程)。
但进程(用户线程)此后要不断轮询用户空间的用户缓冲区是否已经准备好数据,所以一般不推荐使用。
特点:进程(用户线程)要不断轮询recvfrom系统调用,看数据是否已经准备好,直到数据准备好已完成recvfrom系统调用为止。
优点:不会阻塞用户线程。
缺点:需要轮询系统调用,占用CPU资源。
三.IO复用模型
IO多路复用模型就是通过一种新的系统调用,让一个进程(用户线程)可以监视多个连接(文件描述符),一旦某个连接就绪(文件描述符可读可写),那么内核就会通知进程(用户线程)进行相应的IO系统调用。
IO复用模型:两次调用、两次返回,同步IO、阻塞IO。该模型中首先执行的不是recvfrom系统调用,而是select/epoll系统调用。
步骤一:执行select/epoll系统调用查询可以读的连接(就绪的文件描述符)
此时内核会查询所有可以查询的socket列表。当任何一个socket中的数据准备好了之后,select/epoll系统调用就会返回。所以当进程(用户线程)调用了select/epoll系统调用时,是会被阻塞的;
步骤二:进程(用户线程)获得了目标连接(准备好数据的socket)后,会发起recvfrom系统调用,此时进程(用户线程)也会被阻塞。此时数据会从内核缓冲区复制到用户缓冲区,recvfrom系统调用会将数据返回给进程(用户线程)。
select/poll是顺序扫描文件描述符fd是否就绪。epoll是用事件驱动代替顺序扫描,当文件描述符fd就绪时,立即进行回调。
优点:select/epoll可以同时处理成千上万个连接,不必每个连接创建一个线程。
缺点:select/epoll系统调用还是属于同步阻塞IO。
19.IO多路复用技术
IO多路复用技术通过把多个IO的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。
与传统的多线程/多进程模型相比:IO多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或线程,也不需要维护这些线程和进程的运行,降低了系统维护的工作量,节省了系统资源。
20.select、poll、epoll的区别
区别一:
epoll支持一个进程打开的socket描述符fd的数量不受限制。select最大的缺陷是单个进程所打开的socket描述符fd的数量是有限制的,默认1024。epoll在1G内存的机器上可以打开10万左右的连接,内存越大,打开的连接越多。
区别二:
epoll的IO效率不会随着fd数目的增加而线性下降。select/poll每次调用都会线性扫描全部socket集合,导致效率线性下降。epoll是根据每个fd上面的回调函数实现的,只有活跃的socket才会主动调用回调函数。
区别三:
epoll使用mmap加速内核与用户空间的消息传递。为了能让内核把fd消息通知给用户空间,select和poll需要通过内存复制来实现。epoll则通过mmap让内核和用户空间共享一块内存来避免内存复制。