当从主机 A 向主机 B 发起一次 HTTP 请求时,假定为HTTP/1.0协议,即每个请求都建立一个新的TCP连接,以下是整个过程的分析:
一、地址解析和建立连接(三次握手)
- 主机 A(客户机) 中的应用程序(如浏览器)准备发起 HTTP 请求。首先,主机A若刚加入子网,则通过DHCP协议(发现,提供,请求,确认报文都是广播的)获取自己的IP地址。然后,应用程序会告知主机 A 的 TCP 协议准备建立连接,端口为80(熟知端口号:0~1023)。因为UDP一般进行及时的一次性的少数据传输,TCP提供可靠传输(通过流量控制,拥塞控制,重传机制,序列号和确认应答机制,检验和),http本身无连接,无状态(使用Cookie)。
- 当然,在发送数据之前,主机 A 需要确定主机 B 的 IP 地址。如果主机 A 缓存中有B的IP地址,即已经知道主机 B 的 IP 地址,可以直接进行下一步;如果不知道,则需要采用域名系统(DNS)解析,通过发送给ISP的本地域名服务器一个查询请求报文,然后以递归查询或者递归与迭代相结合的查询,来获取主机 B 的 IP 地址。
- 主机 A 的 TCP 向主机 B 发送一个带有 SYN =1(同步位)的 TCP 报文段,该报文段中包含一个随机序列号(假设为 seq = x),不携带数据。这个报文段会被封装在 IP 数据报中,而 IP 数据报又会被封装成数据帧在物理网络中传输。
- 主机 B 收到来自主机 A 的 SYN 报文段后,由其 TCP 协议处理。主机 B 向主机 A 回复一个带有 SYN =1, ACK=1(确认位),ack=x+1(确认号)的 TCP 报文段,其中确认号表示期望收到的下一个序列号(TCP是面向字节流的,一个字节一个序号),同时也包含一个自己的随机序列号(假设为 seq = y),不携带数据。主机B(服务器)进入SYN-RCVD阶段,为该TCP连接分配了缓存和变量。
- 主机 A 收到主机 B 的 SYN + ACK 报文段后,再向主机 B 发送一个带有 ACK =1,ack为 y + 1的 TCP 报文段,可能携带数据(如:可以存放一次http请求),完成三次握手,此时连接建立成功。主机A开始进行资源分配。
二、子网判断
- 主机 A 确定了主机 B 的 IP 地址后,通过子网掩码来判断主机 B 是否与自己在同一个子网中。如果在同一个子网中,则可以直接通过交换机(分为直通式(只检查目的地址),和存储转发式)进行通信(主机号全一为广播地址);如果不在同一个子网中,则需要通过ARP发送给主机A设定的那个默认网关(手动配置或者DHCP配置,实际就是路由器在该子网中的那个端口,如果配置错误也就访问不到路由器了),然后交给路由器(分割广播域)进行通信。值得注意的是,VLAN会分割广播域,位于同一 VLAN 的主机之间可以相互通信,位于不同 VLAN 的主机之间需要借助路由器或者三层交换机进行通信,ARP在同一个VLAN起作用,链接在不同交换机的主机可能属于同一个VLAN。
- 路由表内容包括目的网络IP地址(如202.118.1.0,0.0.0.0),目的网络的子网掩码(如255.255.255.128,0.0.0.0),下一条IP地址(为下一条的路由器连接到本路由器的那个接口的IP地址(如:202.118.2.2),或者Direct(表示目的网络也通过本路由器某个接口连接)),接口号(本路由器连接到下一条路由器的那个接口,或者本路由器的某个接口)。默认路由0.0.0.0(也相当于指代互联网),对应的下一跳IP地址由用户决定(可能是202.118.2.2等等)。可以使用网络聚合的技术,来让路由表表项变少。路由器的功能为路由选择和分组转发,路由表决定转发表。路由器根据路由协议(如域内路由协议RIP、OSPF 和域外路由协议BGP-4等)来确定整个路由表。
三、交换机自学习与数据帧传输(同一子网情况)
- 如果主机 A 和主机 B 在同一子网(用以太网,和存储转发式交换机为例)中,主机 A 会将 HTTP 请求封装成数据帧,数据帧中包含源 MAC 地址(主机 A 的网卡 MAC 地址)、目的 MAC 地址(PDU地址)、IP数据报、类型号、校验码(FCS)。主机 B 的网卡 MAC 地址,如果不知道则使用目的MAC地址全为1的帧来封装并广播一个 ARP 请求,主机B收到向主机A单播发送一个ARP响应分组,来获取主机B的MAC地址。值得注意的是,以太网Mac帧无帧结束符,因为其各帧之间有间隙。若出现帧小于64B,还应该进行填充,以满足CSMA/CD协议。
- 当数据帧进入交换机(可分割冲突域,全双工,总带宽=端口数*一个端口带宽)时,以太网交换机(实际就是多端口网桥)会进行自学习。它会记录下源 MAC 地址和数据帧进入的端口号。如果以太网交换机的 MAC 地址表中已经有了目的 MAC 地址对应的端口号,则直接将数据帧从该端口转发出去;如果没有,则向除了数据帧进入的端口之外的所有端口广播这个数据帧。只有主机B收下这个帧,其他主机丢弃。
- 主机 B 收到数据帧后,进行差错控制检查整个帧(奇偶校验码,CRC)。若出错则直接丢弃。若正确,则检查目的 MAC 地址是否与自己的 MAC 地址匹配。如果匹配,则将数据帧中的 IP 数据报提取出来,并交给上层协议处理。
- 以太网(IEEE802.3)采用总线形拓扑结构,提供无差错传输,使用CSMA/CD进行访问控制,没有流量控制,提供无连接不可靠的服务。但在OSI模型下,数据链路层可提供两个相邻节点的流量控制。而对于IEEE802.11无线局域网(采用CSMA/CA),高速以太网等,又有不同之处。
四、路由选择与分组转发(不同子网情况)
- 路由器收到数据帧后,提取出 IP 数据报。路由器会检查 IP 数据报的目的 IP 地址,并在其转发表中查找与之匹配的条目(最长前缀码匹配),确定将数据报转发到哪个接口。TCP/IP模型下,网络层提供无连接不可靠的数据报服务,由传输层支持无连接和连接两种方式。
- 如果主机 A 和主机 B 不在同一子网中,主机 A 会将数据帧发送相应的网络,如果转发表查询不到对应网络则发给默认路由(通常就是0.0.0.0,路由器有多个IP地址(此IP地址是会占用该接口所处网络中的一个IP地址),和多个硬件地址),在路由表中默认路由条目有时会代替所有有相同下一跳的条目。主机 A 通过 ARP 协议获取默认网关的 MAC 地址,并将数据帧的目的 MAC 地址设置为默认网关的 MAC 地址。主机A若在NAT路由器下,则A发送的IP数据报源地址为内网IP地址,通过NAT路由器转发后,数据报的源地址改为NAT路由器的外网IP地址。对于端口号的设定,比如内网的web服务器默认使用80端口,那么访问外网的端口号也设为80。
- 路由器将 IP 数据报(若大于1500B,且为8B的整数倍)分片(主机和路由器进行IP数据报的分片,在目的主机上封装),重新封装成数据帧,并将数据帧发送到下一跳。这个过程可能会经过多个路由器的转发,直到数据帧到达与主机 B 在同一子网的路由器。转发途中,若ARP高速缓存中,没有对应的IP地址和MAC地址的映射,则需要不断使用ARP协议,更改MAC帧里的源地址和目的地址。即路由器到下一个路由器,若无MAC地址也是通过ARP获取。IP数据报TTL字段(通过一个路由器转发,就减1)减到0时丢弃,特别的,RIP(使用UDP,应用层协议)为只允许15跳,距离为16,表示不可达,丢弃时会给主机A发送一个ICMP差错报文。网络层的首部校验和只检查IP数据报首部,传输层的校验和才会检查首部和数据。
- 最后,该路由器通过交换机将数据帧转发给主机 B,主机 B 收到数据帧后进行处理。(局域网的链路层只能看到MAC帧)
五、数据传输与关闭连接(四次挥手)
- 主机 B 接收到 HTTP 请求后,由其应用程序(如 Web 服务器)进行处理,并向主机 A 发送 HTTP 响应。这个响应同样经过上述的过程从主机 B 传输到主机 A。
- 当数据传输完成后,主机 A 和主机 B 中的 TCP 协议开始进行连接关闭的过程。
- 主机 A 的 TCP 向主机 B 发送一个带有 FIN =1(终止位),seq=u的 TCP 报文段,表示自己没有数据要发送了,希望关闭连接。
- 主机 B 收到 FIN 报文段后,回复一个带有 ACK=1,seq=u,ack=u+1的 TCP 报文段,表示已经收到了 FIN 报文段。客户机A到服务器B这个方向的连接释放,TCP连接处于半关闭状态。
- 主机 B 也向主机 A 发送一个带有 FIN =1,ACK=1,seq=v,ack=u+1的 TCP 报文段,表示自己也没有数据要发送了。
- 主机 A 收到 FIN 报文段后,回复一个带有ACK=1,seq=u+1,ack=v+1的 TCP 报文段,等待2MSL(避免主机A这一次发送的确认报文丢失等一些特殊情况),若再无接受到主机B的报文,则连接正式关闭。