网络协议
链路层:由网卡和网卡驱动完成
传输层和网络层:由操作系统负责
UDP:面向无连接;QQ、DNS
UDT:基于UDP,在应用层自己实现连接、重传;TCP由操作系统实现,算法比较保守;UDT自己实现,可以根据带宽变化迅速调整传输的数据大小;基于光纤、海量数据场景下
移动的4G、5G:属于链路层
MAC地址:属于链路层或是物理层;写在网卡等硬件里面的;物理地址,一共6个字节,48位,前3个字节需要去IEEE申请,后3个字节由设备厂商自己设置;可以理解是唯一的
IP地址:IPV4只有4个字节32位,属于网络层,是逻辑上存在,主要用作通讯子网的区分。可以自己修改,也可以由路由器分配(DHCP服务分配)
子网内的网络寻址:比如通过IP找到子网以后,数据就到了子网的路由器,路由器上保存了每个电脑的MAC地址和IP地址,路由器会把数据包里面的MAC地址改为当前子网里面IP地址对应设备的MAC地址。数据是会通过广播的方式发送,每台计算机都会收到,但是计算机的网卡会快速判断数据包里的MAC地址是不是自己,不是就丢弃
网络嗅探:就是不让网卡把非本机MAC地址的数据丢弃,这个前提是必须在同一个子网里面
端口号:用来识别同一台计算机中进行通信的不同应用程序,也被称为程序地址。0-1023是知名端口号,比如SSL是22,Http是80;服务端程序一般会显示指定端口号,客户端一般不用指定,操作系统会分配,一般是49152-65535之间。1024-49151之间一般不要使用,可能有知名应用程序使用。每个应用程序用的端口不一样。
通过源IP地址、目标IP地址、协议号TCP、源端口号以及目标端口号这5个元素识别一个通信
TCP
- 面向连接
- 可靠性:超时重传,应答确认机制确保。往返时延,数据往返一趟的时间,用于操作系统进行重传超时时间的计算确定,这个超时时间是动态的
- 数据排序:TCP的连接是虚拟连接,所对应的物理连接线路有可能有多条路径,实际上三次握手所发送接收的数据走的可能是不同的路线。这就导致我们发送的数据在拆分成片后,到达目的地服务器的顺序是不一样的。TCP会在数据包都到了以后重新排序打包成新的包然后再传给应用层协议
- 流量控制:服务端会返回给客户端当前自己能处理的数据量,让客户端下次传输对应大小的量,达到流量控制;也叫滑动窗口,意味着接收方还有多大的缓冲区可以用于接收数据
- 全双工:2端可以同时进行传输和接收
三次握手
客户端Connect方法:发送3次数据包的过程
- 客户端发送:SYN=1,seq=23412(序列号),进入SYN_SENT状态;
- 服务端收到后,发送:SYN=1,ACK=1,ack=23413(客户端的seq 1),seq=6478(序列号),进入SYN_RCVD状态
- 客户端收到,发送:ACK=1,ack=6479(服务端的seq 1),进入ESTABLISHIED状态,服务端收到后也进入这个状态
- SYN和ACK都是标志位
为什么需要3次握手?
告诉通讯双方序列号的起始值,后续通信就会在序列号的起始值上进行累加,比如起始值 数据长度,这样如果出现丢包,就知道该从哪里开始重传。
3次握手需要确定双方都收到了对方的序列号起始值。以最小的发送次数保证连接的可靠
TCP的3次握手漏洞--SYN洪泛攻击
通过向服务端发送大量伪造IP地址的握手请求,使服务端一直处于等待客户端应答握手的状态,消耗服务端资源。
解决办法:防火墙、无效连接监控释放
4次挥手
发起人既可以是客户端也可以是服务端
- 客户端发送:FIN=1,seq=98745(序列号),进入FIN_WAIT_1状态
- 服务端收到后,发送:ACK=1,ack=98746(上面 1),进入CLOSE_WAIT状态;客户端收到后,进入FIN_WAIT_2状态
- 服务端发送:FIN=1,seq=76432(序列号),服务端进入CLOSE状态
- 客户端收到后,发送:ACK=1,ack=76433(上面的 1),客户端进入TIME_WAITING状态;服务端收到后进入CLOSED状态
- 客户端会等待2*MSL的时间再进入CLOSED状态,MSL叫做最长报文段的寿命(存活的最长时间),在官方的RFC文档中定义为2分钟,实际操作系统一般是30秒。所以客户端这个TIME_WAITING状态的持续时间一般是1分钟-4分钟。客户端进入CLOSED状态后,TCP连接就结束了
为什么挥手需要4次?
TCP是全双工,需要双方都确认没有数据再发送和接收。
- 客户端:我没有数据要发送给你了 ---客户端FIN_WAIT_1
- 服务端:好的,我知道你没有数据要发了。---服务端CLOSE_WAIT,客户端FIN_WAIT_2
- 服务端:我也没有数据要发给你了。---服务端CLOSE,客户端TIME_WAITING
- 客户端:好的,我知道你也没有数据发送给我了 --- 服务端CLOSED
- 客户端CLOSED
为什么服务端的ACK报文和FIN报文不一起发送(第2、3步合并)?
实际情况下是存在这种合并发送的情况的,客户端的FIN报文也可能会和最后的数据报文一起发送
为什么主动发起挥手方有TIME_WAITING状态?还要等待那么长的时间?
- 服务端发送的FIN报文有可能会丢失,服务端会重发,客户端这边需要存活一段时间确保给服务端发送ACK报文并收到;
- 第2个原因是端口复用的问题,如果直接进入CLOSED状态,端口就可能被其他应用占据,但此时服务端可能还有报文没发送完。TCP规定处于TIME_WAITING时端口是不会释放的。
- 总结就是:可靠的终止TCP连接;保证迟来的报文被识别并且丢弃
TCP超时机制
- 如果TIME_WAITING时间到了,服务端还没有收到ACK报文,会认为连接出问题了,会主动关闭连接
- 网络异常中断时不会有4次挥手,会启动TCP超时机制
TCP的拆包和粘包
拆包
数据在进行网络传输的时候,链路层限制了每次传送的大小,比如是1460个字节,那网络层的IP层就会对数据进行分片传送,这样接收端接收到的数据就不是完整的包
粘包
数据传输时,有可能每次传送的数据包很小,这样每次都需要接收端确认再传下一个包,于是就有了nagle算法,把这些小的数据包合并成一个包一起传输
解决方式
- 加个数据包的报文头,记录数据包的大小
- 消息定长,就是规定每次报文的消息长度固定
- 特殊的分割符,分割出报文,比如FTP协议就是通过回车换行符来分割
抓包工具Wireshark
- 安装时需要选择Npcap
- BPF 语法可以用来创建过滤器
抓包方法:tcpdump
tcpdump -i eth0 tcp port 3306 -w ./mysql.cap
打开一个网页完整http请求的过程
- 首先进行DNS域名解析(本地浏览器缓存、操作系统缓存、DNS服务器)
- 三次握手建立TCP连接
- 客户端发起HTTP请求
- 服务端响应HTTP请求
- 客户端解析Html代码,并请求html代码中的资源
- 客户端渲染展示内容
- 关闭TCP连接
其他
抓包原理:操作系统级别,允许越过传输层和网络层,直接操作链路层网卡实际收到的数据
END
点赞转发,让精彩不停歇!关注我们,评论区见,一起期待下期的深度好文!