美文网首页
TCP/IP学习

TCP/IP学习

作者: 知而乐者 | 来源:发表于2021-03-13 11:36 被阅读0次

    网络7层模型和TCP/IP四层模型

    image.png

    HTTP和TCP/IP有什么不一样?
    http是应用层的协议,tcp为传输层的协议。http是计算机用户自定义的一种协议,本身就行,前几个字节代表什么,以什么来分割信息等,避免网络传输过程中拆包和粘包的问题。

    tcp/ip为数据传输协议,是计算机内部封装的协议,在各个网络之间去寻找目的主机进行数据的传输。

    TCP各个阶段

    image.png

    在Linux下可以通过,netstat -antp查看链接的状态。包括:
    client端,SYN-SEND:握手信息发送(SYN,和一个随机的SEQ)
    server端,SYN-RCVD:收到SYN,回复一个SEQ+1的ACKNUM以及一个随机的SEQ
    client端,ESTABLISED收到server端的回复
    server端,ESTABLISED收到client端的回复
    两端都可能(可能同时),FIN-WAIT-1:第一个发起关闭
    两端都可能(可能同时),FIN-WAIT-2:收到关闭确认
    收到关闭消息的一端:CLOSE-WAIT:收到关闭消息
    收到另一方的关闭,TIME-WAIT

    为什么需要三次握手和四次挥手?

    三次握手来确保两端的接收和发送能力。
    四次挥手因为TCP是全双工通信的

    为什么要有TIME_WAIT阶段,并且要保持60s?

    如果主动方不保留 TIME_WAIT 状态,会发生什么呢?此时连接的端口恢复了自由身,可以复用于新连接了。然而,被动方的 FIN 报文可能再次到达,这既可能是网络中的路由器重复发送,也有可能是被动方没收到 ACK 时基于 tcp_orphan_retries 参数重发。这样,正常通讯的新连接就可能被重复发送的 FIN 报文误关闭
    为什么 TIME_WAIT 状态要保持 60 秒呢?这与孤儿连接 FIN_WAIT2 状态默认保留 60 秒的原理是一样的,因为这两个状态都需要保持 2MSL 时长。MSL 全称是 Maximum Segment Lifetime,它定义了一个报文在网络中的最长生存时间(报文每经过一次路由器的转发,IP 头部的 TTL 字段就会减 1,减到 0 时报文就被丢弃,这就限制了报文的最长存活时间)。

    TIME_WAIT 状态的存在是有必要的,但它毕竟在消耗系统资源,比如 TIME_WAIT 状态的端口就无法供新连接使用。怎样解决这个问题呢?

    Linux 提供了 tcp_max_tw_buckets 参数,当 TIME_WAIT 的连接数量超过该参数时,新关闭的连接就不再经历 TIME_WAIT 而直接关闭。net.ipv4.tcp_max_tw_buckets = 5000
    当服务器的并发连接增多时,相应地,同时处于 TIME_WAIT 状态的连接数量也会变多,此时就应当调大 tcp_max_tw_buckets 参数,减少不同连接间数据错乱的概率。当然,tcp_max_tw_buckets 也不是越大越好,毕竟内存和端口号都是有限的。有没有办法让新连接复用 TIME_WAIT 状态的端口呢?如果服务器会主动向上游服务器发起连接的话,就可以把 tcp_tw_reuse 参数设置为 1,它允许作为客户端的新连接,在安全条件下使用 TIME_WAIT 状态下的端口。
    net.ipv4.tcp_tw_reuse = 1

    一个数据包的流转

    比如我要访问google,在浏览器里输入域名,点击回车会发生什么?
    1、首先由于是在浏览器里的请求,所以走的是http协议,会将我的请求封装成http数据格式,如:消息头,消息体,然后就需要将这些消息发送给google

    2、如何知道google服务器在哪台服务器上使用哪个端口呢?在浏览器里输入的域名通过DNS解析可以拿到google服务器的地址,域名通过冒号分割可以拿到端口(没有的话默认是80,https默认是443)。

    3、应用程序(应用层)就知道要发往哪个IP哪个端口数据了,以及使用什么协议(TCP还是UDP,假设使用TCP)此时交给操作系统,操作系统通过协议将数据进行封装

    4、将应用层给的数据封装成tcp协议格式(在发送数据前增加TCP协议头),会包含源端口号,目标端口号,一些TCP使用的数据以及要发送的数据(发送的数据及http的消息头和消息体)


    image.png

    5、将数据封装成TCP协议格式后,会将数据交给下一层IP层,此时,会在TCP数据包前增加IP头,主要包括源IP和目的IP,数据协议类型


    image.png

    6、通过配置的网关就可以知道源IP是多少,将数据发送到哪个网关,可以通过route -n来查看网关信息,也能确定使用哪个网卡来进行发送

    7、如何将数据发送给网关内?此时就需要在IP头部在封装一下MAC头部,用于在两个机器之间的传输,计算机只是知道网关的IP并不知道网关机器的MAC地址,此时就需要使用ARP协议来发送广播询问IP对应的MAC地址,之后将IP头部的封装MAC头部(包含源MAC和目标MAC)源MAC就是网卡的MAC

    8、如果计算机和网关之间通信使用了交换机,交换机是二层网络设备里会存储链接到交换机上每个端口的计算机的MAC地址,就知道将数据发送到哪个端口

    9、网关收到后就会发送给路由器进行网络之前的传输,路由器是三层设备,每个端口都有对应的MAC地址和IP地址,路由器也会保存每个端口对应的MAC地址,IP地址和子网掩码,路由器拿到之后就知道要发网哪个端口,最终发送到对应IP的机器

    10、到达目标机器的网络后进行拆包,最终找到机器的进程

    11、NGINX可能是最后的进程,监听的是80端口,所以nginx工作在第七层,可以通过域名等来进行转发(工作在四层的机器只能解析到IP通过IP进行转发)

    12、应用程序收到之后进行数据的解析,之后将数据返回

    等待解决问题:
    源IP问题,在数据包传输过程中,目的IP和源IP是没有变化的,那么客户端在封装数据包时怎么拿到的公网IP?
    在经过网关的时候,如果发现目的IP会进行NAT转换,即把源IP换成网关的公网IP,同时会维护一个关系表,在返回数据的时候可以找到客户机器,在公网上经过路由器的时候,是路由操作不会替换拆包替换原IP
    192.168.1.120:400-》192.168.1.1:500
    192.168.1.121:600-》192.168.1.1:800
    Nginx问题,Nginx工作在第七层,所以当操作系统收到数据包后一步一步的解析完,交给的Nginx应用程序只是,http数据,Nginx是怎么拿到真实的源IP的?
    Nginx拿到的整个数据包信息,可以得到源IP地址

    相关文章

      网友评论

          本文标题:TCP/IP学习

          本文链接:https://www.haomeiwen.com/subject/cyqxcltx.html