网络是怎样连接的(以访问网页为例)第一篇章(重点)——客户端出发点

生成HTTP请求消息

网址(URL)的输入

浏览器是一个具有多种客户端功能的综合性客户端软件,因此需要各种各样的URL来判断应该使用其中哪种功能的综合性客户端软件。

URL开头文字,即:“http:” “tfp:” “file” …表示的是浏览器应当使用的访问方法。
在这里插入图片描述

浏览器解析URL(以访问web服务器为例)

浏览器第一步工作就是解析URL,从而生成发送给web服务器的请求消息。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用HTTP协议来访问web服务器

在这里插入图片描述
上一步在对URL进行解析之后,浏览器确定了web服务器和文件名,接下来就是根据这些信息来生成HTTP请求消息了。HTTP消息在格式上有严格的规定,因此浏览器会根据规定的格式生成请求消息。
在这里插入图片描述

HTTP协议定义了客户端和服务器之间交互的消息内容操作方法


当上述的请求消息发送出去之后,web服务器会返回响应消息
在这里插入图片描述
注:尽管浏览器能够解析网址并生成HTTP消息,但它本身并不具备将消息发送到网络中的功能,它的实际发送还需依靠其他协议继续封装并依托操作系统来实现,以上只是HTTP消息的格式。

向DNS服务器查询web服务器的IP地址

TCP/IP网络是通过IP地址来确定通信对象的。

TCP/IP的基本思路:由一些小的子网,通过路由器连接起来组成一个大的网络。 子网可以理解为用集线器连接起来的几台计算机。
在这里插入图片描述

IP地址

IP地址:一串32bit的数字,按照8bit为一组分为4组,常见IP地址是用十进制表示的。
网络号和主机号是通过子网掩码来确定的。
在这里插入图片描述
ip地址主机号
全0:表示整个子网
全1:表示向子网上所有设备发送包(广播)

域名和IP地址并用的理由

TCP/IP网络是通过IP地址来确定通信对象的。

网址中不写服务器名字,直接写IP地址???
实际上,用IP地址来代替服务器名称也是能正常工作的。之所以网址中写域名而不直接写IP地址,是因为IP地址和电话号码一样在记忆使用上比较困难。

不用IP地址,用名称来确定通信对象???
IP地址占四个字节,而域名最短也要几十个字节,最长甚至可以达到255字节,这无疑增加了路由器的负担,传送数据也会花费更长时间。

Socket库提供查询IP地址的功能

查询IP地址的方法非常简单,只要询问最近的DNS服务器就可以了,DNS服务器会将目标IP地址返回请求方。

有Web服务器,就有主机客户端。同理对于DNS服务器,就有DNS客户端。DNS解析器就相当于DNS客户端。DNS解析器是一段程序,它包含在操作系统的Socket库中。Socket库是 用于调用网络功能的程序组件集合。

工作流程:
在这里插入图片描述
①:应用程序顺序执行,到达运用解析器部分,对应行程序被执行,应用程序本身会暂停。
②:Socket库中的解析器开始运行,完成委托。
③④⑤:解析器按照DNS格式生成DNS查询消息,然后委托操作系统协议栈,最后通过网卡将消息发送给DNS服务器。
⑥IP地址被写入响应消息并返回给客户端。
⑦⑧消息经过协议栈被传递给解析器。
⑨解析器读取出消息中的IP地址,并将IP地址传递给应用程序。

向DNS服务器发送消息时,当然也需要事先知道DNS服务器的IP地址,不过这个IP地址是事先设置好的,不需要去查询。


DNS服务器之间的查询操作:
在这里插入图片描述

委托协议栈发送消息

知道了IP地址之后,就可以委托操作系统内部的协议栈向目标IP地址,也就是我们要访问的web服务器发送消息了。和向DNS服务器查询IP地址的操作一样,这里也需要使用Socket库中的程序组件。
使用Socket库来收发数据就是要在两台计算机之间连接一条数据通道,数据沿着这条通道流动,最终到达目的地。

协议栈结构:
在这里插入图片描述
通俗的来讲协议栈的功能: 就是将数据封装成具有跨网络传输功能并且通信双方软硬件够能够识别的数据块。
例如:计算机和手机能够相互通信,Windows操作系统与Linux操作系统之间可以互相通信。

什么是套接字

在进行收发数据操作之前,双方需要先建立起这条管道才行。建立管道的关键在于管道两端的数据出入口,这些出入口称为套接字。

套接字只是一个概念,并不存在实体,但我们可以把套接字理解为具有各种各样通信控制信息(例如IP地址、端口号、通信操作的进行状态)的通信出入口。
套接字内容:
在这里插入图片描述

综上所述:收发数据的操作分为若干个阶段,可以大致总结为以下4个阶段:
在这里插入图片描述

创建套接字(打开数据出入口)

客户端创建套接字就是调用Socket库中的socket程序组件,和调用解析器一样。创建套接字时,首先分配一个套接字所需的内存空间,然后向其中写入初始状态。
套接字创建完成之后,协议栈会返回一个描述符,描述符是用来识别不同的套接字的。例如浏览器在访问两台web服务器,此时的计算机与两台服务器之间进行数据交换的通信控制信息也必定是不同的。描述符就用来标识这两条数据出入口——也就是套接字。应用程序是通过描述符来识别套接字的。
接下来,需要将表示这个套接字的描述符告知应用程序,收到描述符后,应用程序在向协议栈进行收发数据委托时就需要提供这个描述符。

连接阶段(将双方数据出入口相连——三次握手)

在双方套接字刚刚创建完成的时候,里面并没有存放任何数据,也不知道通信的对象是谁。
请求端:只有浏览器器知道必要的通信信息(对象IP,端口号等),但这些信息还没有传递给协议栈。
服务端:应用程序根本不知道通信对象是谁,只有等待请求连接。

连接阶段的任务:
1.请求端:把服务器的IP地址和端口号告知协议栈。
2.客户端向服务器传达开始通信的请求。
在这里插入图片描述

实际过程三次握手:

参考博客: https://blog.csdn.net/baiyan3212/article/details/81302448.
第一次握手: 客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN。此时客户端处于 SYN_SENT 状态。
首部的同步位SYN=1,初始序号seq=xSYN=1的报文段不能携带数据,但要消耗掉一个序号。

第二次握手: 服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_RCVD 的状态。
在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。此报文段也不能携带数据(第一次请求端将信息发来之后,服务器端就知道了请求端的IP地址,端口号等通信控制信息)

第三次握手: 客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接。
确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。
在这里插入图片描述
ack:确认编号,即接收到的上一次远端主机传来的seq然后+1,再发送给远端主机。提示远端主机已经成功接收上一次所有数据。
ACK:确认值,为1表示确认连接。

为什么要三次握手?

第一次握手:客户端发送网络包,服务端收到了。
这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
第二次握手:服务端发包,客户端收到了。
这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端发包,服务端收到了。

原因一:这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
双方都必须确认自己和对方的发送和接收能力都是正常的。

原因二:防止已经失效的连接请求报文段突然又传到B,因而产生错误。
在这里插入图片描述

三次握手过程中可以携带数据吗

第三次握手时可以携带数据,但是第一、二次不行。

原因:设想这样的场景:若第一次握手可以携带数据,有人要恶意攻击服务器,则他每次都可以在第一次握手中的SYN报文中放入大量数据,会让服务器花费很多时间、空间来处理报文。
这就是SYN攻击: Client在短时间伪造大量不存在的ip地址,向Server不断发送SYN包,Server则回复确认包,并等待Client确认,这些包将长时间占用未连接队列,导致正常的SYN请求因为队列满被丢弃,从而引起网络拥塞甚至系统瘫痪(Dos/DDoS攻击)

也就是说:第一次握手无法放数据,保证了服务器的安全性。而第三次握手时,已经代表成功的建立了连接,从客户端携带数据到服务器也是被理解的。

通信阶段(根据通道进行数据交换)

序号与ack号用法

图中ACK表示的是确认编号。
在这里插入图片描述

使用窗口有效管理ack号

每发一个包就等待一个ack号,在等待ack号的这段时间中,如果什么都不做那实在太浪费了,为了减少浪费,TCP采用窗口滑动方式来管理数据发送和ack号。即:发送一个包之后,不等待ack号返回,而是直接发送后续的一系列包。
在这里插入图片描述
并且为避免发送的包太多,接收方可能会处理不过来的情况,会将数据放到接受缓冲区也就是窗口大小。并将窗口大小和数据一起发送给发送方,表示自己的最大接收能力。
在这里插入图片描述

在这里插入图片描述

断开管道并删除套接字(断开通道和出入口——四次挥手)

为什么建立一个连接要三次握手,而终止需要四次呢?这是由TCP的半关闭造成的。即,TCP提供了连接的一段在结束它的发送后还能接收来自另一端数据的能力。
双方均可主动发起挥手

假设客户端先发起关闭请求:

第一次挥手: 客户端发送一个FIN报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。
即:报文段:FIN=1,seq=u。 客户端进入FIN_WAIT1状态。
FIN报文段即使不携带数据,他也消耗掉一个序号。

第二次挥手: 服务器收到FIN后,会发送ACK报文,且把客户端序列号值+1作为ACK报文的序列号值,表示已经收到客户端的报文了,此时服务器处于CLOSE_WAIT状态。
即:报文段:ACK=1,ack=u+1,seq=v。服务器进入CLOSE_WAIT状态。客户端收到服务端的确认后,进入FIN_WAIT2状态,等待 B发送FIN报文。
这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A任然要接受。也就是说,从B到A这个方向的连接并没有关闭,这个状态会持续一段时间

第三次挥手: 如果服务器也想断开连接了,发送FIN报文,并且由于这是对于回应报文,因此确认标志ACK仍需置1,服务器端处于LAST_ACK状态
即:报文段:ACK=1,FIN=1,ack=u+1(仍算是对seq=u的回应),seq=w。,服务器进入LAST_ACK状态。

第四次挥手: 客户端收到FIN后,发送一个ACK作为应答,此时客户端处于TIME_WAIT2状态,而服务端收到ACK报文后,就处于CLOSED状态.
即:报文段:ACK=1,seq=u+1(第一次为seq=u),ack=w+1。客户端进入TIME_WAIT状态,此时TCP还未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。
在这里插入图片描述

挥手为什么需要四次

当服务器端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”,只有等我服务端所有的报文都发送完毕, 我才能发送FIN报文。

等待2MSL的意义

MSL译为“最长报文段寿命”,是任何报文在网络上存在的最长时间,超过这个时间,报文将被丢弃。

理由一:保证客户端发送的最后一个ACK报文段能够到达服务端。

若客户端发送的最后一个ACK报文段在传输过程丢失,服务器接受不到回应,会超时重传一次FIN+ACK,而客户端就能在2MSL时间内收到这个重传的FIN+ACK,并且也重传一次确认,重新启动2MSL计时器。最后,双方都正常进入到CLOSED阶段

假设客户端在TIME-WAIT阶段不等待2MSL,而是在发送完ACK后直接释放关闭,一旦这个ACK丢失的话,服务器就无法正常进入关闭连接状态。

理由二:防止“已失效的连接请求报文段”出现在本连接中
A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GuochaoHN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值