您的位置:首页 > 理论基础 > 计算机网络

网络通信学习(二)——用电信号传输TCP/IP数据,探索协议栈和网卡

2019-04-05 09:53 507 查看

前面我们从解析浏览器中输入的网址开始,探索了生成HTTP请求消息、委托操作系统发送消息等步骤。现在,我们来探索操作系统中的网络控制软件(协议栈)和网络硬件(网卡)是如何将浏览器的消息发送给服务器的

本文结构按照数据传输过程划分:

  • (1)创建套接字过程
  • (2)连接服务器过程
  • (3)收发数据过程
  • (4)断开连接过程

深入探究创建套接字的过程,初步窥探协议栈的内部结构和套接字的实体(创建套接字过程)

协议栈内部如图:

套接字的实体就是通信控制信息

在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,如通信对象的IP地址、端口号、通信操作的进行状态等。这块存放控制信息的内存空间就是套接字的实体,协议栈就是根据套接字中记录的控制信息来工作的。
在windows中用netstat命令可以显示套接字内容。

调用socket时的操作

参考网络通信学习(一)

“连接到服务器”这个过程协议栈到底是如何工作的,客户端和服务器是如何进行交互的?(连接服务器过程)

套接字刚刚创建完成的时候,里面并没有存放任何数据,也不知道通信对象是谁。“连接”实际上是通信双方交换控制信息,同时在内存空间分配一块用于临时存放收发数据的缓冲区

负责保存控制信息的头部是什么样子?

TCP头部格式:

TCP头部各部分含义:

字段 长度(比特) 含义
发送方端口号 16 网络包发送方的端口号
接收方端口号 16 网络包的接收方端口号
序号 32 发送方告知接收方该网络包发送的数据相当于所有发送数据的第几个字节
ACK号 32 接收方告知发送方接收方收到了所有数据的第几个字节
数据偏移量 4 表示数据部分的起始位置
保留 6 保留
控制位 6 URG:紧急指针字段有效
ACK:接收数据序号字段有效,一般表示数据已被接收方收到
PSH:通过flush操作发送的数据
RST:强制断开连接,用于异常中断
SYN:相互确认序号,表示连接操作
FIN:表示断开连接
窗口 16 接收方告知发送方窗口大小(即无需等待确认可以一起发送的数据量)
校验和 16 用来检查是否出现错误
紧急指针 16 表示应紧急处理的数据位置
可选字段 可变 其它可选字段

“连接”的具体操作过程——三次握手

  • 首先,客户端先创建一个包含表示开始数据收发操作的控制信息的头部(如TCP头部格式如上表),然后我们将头部的控制位的SYN置1,此外还需要设置适当的序号和窗口大小等。
  • 当TCP头部创建好之后,TCP模块把信息发送给IP模块,IP模块执行发送操作后,网络包沿着网络到达服务器;服务器IP模块把接收到的信息发送给TCP模块,TCP模块根据TCP头部的端口号找到相应的套接字,套接字写入相应信息此时状态变为ESTABLISHED(正在连接)。服务器模块返回响应,在TCP头部设置发送方和接收方的端口号以及SYN,把ACK控制位设为1,同样的过程把响应包发送给客户端。
  • 客户端接收到响应包,如果SYN=1则表示连接成功,这时套接字中会写入服务器的IP地址和端口号等信息,同时将状态改为LISTENING(连接成功),相应的客户端也会返回一个SYN控制位为1的返回包给服务器,服务器接收到返回包后连接操作全部完成。

连接完成后,数据是怎么保证准确无误的发送与接收的?(收发数据过程)

数据收发操作是从应用程序调用write将要发送的数据交给协议栈开始的。

  • 首先,协议栈并不关心应用程序传来的是什么内容。在协议栈看来,数据不过是具有一定长度的二进制字节序列而已。
  • 其次,协议栈并不是一收到数据就马上发送出去,而是放在缓冲区等待。如果一收到数据就马上发出去,数据包就会有的大有的小,小包数量一多就会导致网络效率下降,因此需要在数据积累到一定量时再发送出去。判断要素有两个:(1)每个网络包能容纳的数据长度。MTU代表一个网络包的最大长度,以太网中一般为1500字节;MSS代表除去头部之后一个网络包所能容纳的TCP数据的最大长度,以太网中一般为1460字节。(2)时间。当应用程序发送数据的频率不高的时候,为了防止等待时间过长,协议栈内部计时器会在一定时间后把网络包发送出去。

如果是长度优先,网络效率会提高;如果是时间优先,那么延迟会变小,但是降低网络效率。具体权衡是由协议栈的开发者决定的。

  • 然后,客户端通过序号和ACK号确认网络包的发送状态。TCP模块再拆分数据时,会先算好每一块数据相当于从头开始的第几个字节,并写入TCP头部以便于数据收发检查,这就是序号。实际上序号并不都是从1开始,而是随机计算出一个初始值,这是为了防止有人利用这一点进行信息攻击,设定随机数那么外界就不清楚序号是从多少开始的,也因此需要在开始收发数据之前将序号初始值告知通信对象。另外服务器会把目前收到的数据长度的字节数的值写入TCP头部的ACK号中,并返回给客户端,这个返回ACK号的操作被称为确认响应,发送方可以通过确认相应得知对方到底收到多少数据。具体过程如图:

TCP采用这样的方式确认对方是否收到了数据,在收到返回包响应的ACK号前,发送过的包都会保存在发送缓冲区,如果没有收到返回包,那么就重传响应的包。这一机制非常强大,通过这一机制我们可以确认接收方有没有收到某个包,如果没有收到则重新发送,这样一来,无论网络中发生任何错误,我们都可以发现并采取补救措施(重传网络包)。反过来说,有了这一机制,我们就不需要在其他地方对错误进行补救了。因此,网卡、集线器、路由器都没有错误补偿机制,一旦检测到错误就直接丢弃相应的包。

  • 前面说的只是基本原理,实际上网络的错误检测和补偿机制非常复杂。(1)返回ACK号的等待时间(也叫超时时间)。当网络传输繁忙时发生拥塞时,可能会出现已经重传了包之后,返回的ACK号才姗姗来迟,这样的重传加重了网络的负担。所以等待时间需要设置一个合适的值,这个时间长短是根据ACK号返回所需时间来判断的。具体来说,TCP会在发送数据过程中持续测量ACK号返回时间,慢则等待时间延长,快则等待时间缩短。(2)使用窗口来有效管理ACK号。 所谓滑动窗口,就是指在发送一个包之后,不等待ACK号返回,而是直接发送后续的一系列包。具体分析:当接受方的TCP收到包后,会将数据存放到缓冲区,然后接收方计算此时的ACK号,将数据块组装起来还原成原本的数据传递给应用程序。如果数据到达的速率比处理这些数据并传递给应用程序的速率还要快,那么缓冲区的数据就可能出现溢出。所以:接收方需要告诉发送方自己能接受多少数据,然后发送方根据这个值对数据发送操作进行控制,这就是滑动窗口方式的基本思路。(3)ACK号和窗口的合并。接收方在发送ACK号和窗口更新时,会等待一段时间发送。举个例子,在等待发送ACK号时正好需要更新窗口,这时就可以把ACK号和窗口更新放在一个包里发送,从而减少包的数量;在需要连续发送多个ACK号时,可以只发送最后一个ACK号,窗口更新亦如此,等待时间内只需要发送最终结果就可以了。

收发数据全部结束后,套接字将何去何从?(断开连接过程)

“断开连接”的具体操作过程——四次挥手

  • 首先,主动断开方(假设为服务器)会调用Socket库的close程序,这时服务器的协议栈会生成FIN控制位为1的TCP头部,协议栈委托IP模块将FIN包发送出去,服务器协议栈的套接字中会记录下断开操作的相关信息
  • 然后,被动段开方(假设为客户端)收到FIN包后,客户端的协议栈会将自己的套接字标记为进入断开操作状态,并返回一个ACK包给服务器。
  • 接着,客户端调用close程序,并生成一个FIN为1的包,委托给IP模块发送出去。
  • 最后,服务器返回ACK号,通信全部结束。

套接字“功成身退”

通信结束后,套接字完成了它的使命,迎来它的将是被删除以释放占用的内存空间。但是,套接字并不会立即被删除,而是等待一段时间后再被删除,这是为了防止误操作。原因分析:如果最后客户端返回的ACK号丢失了,服务器没有接收到ACK号就会重发一次FIN,然而客户端已经把套接字删除了,套接字对应的端口号被释放,恰巧这个端口号又分配给了一个新的套接字,这时FIN包就会使新套接字删除,结果发生了错误。

数据收发操作过程小结

到这里,用TCP协议收发应用程序数据的操作就全部结束了。这部分内容的讲解比较长,所以最后我们再整理一下。

  • 数据收发操作的第一步是创建套接字。一般来说,服务器一方的应用程序在启动时就会创建好套接字并进入等待连接的状态。客户端则一般是在用户触发特定动作,需要访问服务器的时候创建套接字。在这个阶段还没有开始传输网络包。
  • 创建套接字之后,客户端会向服务器发起连接操 20000 作。首先,客户端会生成一个SYN为1的TCP包并发送给服务器(图2.13①)。这个TCP包的头部还包含了客户端向服务器发送数据时使用的初始序号,以及服务器向客户端发送数据时需要用到的窗口大小。当这个包到达服务器之后,服务器会返回一个SYN为1的TCP包(图2.13②)。和(图2.13①)一样,这个包的头部中也包含了序号和窗口大小,此外还包含表示确认已收到包①的ACK号。当这个包到达客户端时,客户端会向服务器返回一个包含表示确认的ACK号的TCP包。到这里,连接操作就完成了,双方进入数据收发阶段。
  • 数据收发阶段的操作根据应用程序的不同而有一些差异,以Web为例,首先客户端会向服务器发送请求消息。TCP会将请求消息切分成一定大小的块,并在每一块前面加上TCP头部,然后发送给服务器。TCP头部中包含序号,它表示当前发送的是第几个字节的数据。当服务器收到数据时,会向客户端返回ACK号(图2.13⑤)。在最初的阶段,服务器只是不断接收数据,随着数据收发的进行,数据不断传递给应用程序,接收缓冲区就会被逐步释放。这时,服务器需要将新的窗口大小告知客户端。当服务器收到客户端的请求消息后,会向客户端返回响应消息,这个过程和刚才的过程正好相反(图2.13⑥⑦)。
  • 服务器的响应消息发送完毕之后,数据收发操作就结束了,这时就会开始执行断开操作。以Web为例,服务器会先发起断开过程。在这个过程中,服务器先发送一个FIN为1的TCP包(图2.13⑧),然后客户端返回一个表示确认收到的ACK号(图2.13⑨)接下来,双方还会交换一组方向相反的FIN为1的TCP包(图2.13⑩)和包含ACK号的TCP包。最后,在等待一段时间后,套接字会被删除。

前面我们说协议栈把数据委托给IP模块发送出去,那么IP模块到底使如何将包发送出去的?(IP和以太网的包收发操作)

发送方和接收方统称为终端节点,相应的,转发设备被称为转发节点或中间节点。

  • 起点,TCP模块在数据前加上TCP头部后,整个网络包传给IP模块,委托IP模块发送包。
  • IP模块负责添加两个头部:(1)MAC头部(2)IP头部。
  • 网卡将数字信号转换为电信号,通过网线发送出去,经过集线器、路由器等转发设备,一步步送达接收方。
    IP头部格式:

    IP头部各部分含义:
字段 长度 (比特) 含义
版本号 4 IP协议版本号
头部长度 4 IP头部的长度
服务类型 8 表示包传输优先级
总长度 16 IP消息的总长度
ID号 16 用于识别包的编号,一般为包的序列号。如果一个包被IP分片,则所有分片都拥有相同的ID
标志 3 2比特代表是否允许分片,1比特代表是否分片
分片偏移量 13 表示当前包的内容为整个IP消息的第几个字节开始的内容
生存时间TTL 8 包的生存时间,每经过一个路由器值减1,值为0包被丢弃
协议号 8 十六进制
TCP:06
UDP:17
ICMP:01
头部校验和 16 用于检查错误
发送方IP地址 32 发送方IP
接收方IP地址 32 接收方IP
可选字段 可变长度 其它控制信息

MAC头部字段:

字段 长度(比特) 含义
接收方MAC地址 48 接收方MAC地址
发送方MAC地址 48 发送方MAC地址
以太类型 16 IP:0800
ARP:0806
IPv6:86DD
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐