一个数据包从发送到接收都经历了那些过程
1.启动应用程序新建邮件,将收件人邮箱和邮件内容填写好,应用程序进行编码处理。(应用层)
2.应用在发送邮件那一刻建立TCP连接(三次握手),将数据交给传输层。
第一次握手:建立连接时,主机A向主机A发送请求报文
第二次握手:主机B收到请求报文后,如同意连接,则向主机A发送确认报文
第三次握手,主机A收到主机B的确认后,再次向主机B给出确认报文,完成连接
3.TCP就会把这个数据构成一个TCP数据报(附加上TCP首部包括源端口号和目标端口号(用以识别发送主机跟接收主机上的应用)、序号(标明发送的包那部分是数据)以及校验和(判断数据是否被更改)),然后将该数据报交给IP协议(网络层)。
4.IP协议就会构造一个IP数据报(IP会将TCP传过来的数据报当作自己的数据,加上IP首部包含接收端IP地址以及发送端的IP地址),此处要根据数据报的长度,以及MTU的限制,考虑是否进行分包,查路由表决定从哪一个端口转发,将数据交给数据链路层;
5.数据链路层将数据构造一个以太网数据帧,其中以太网首部包含接收端MAC地址、发送端MAC地址以及标志以太网类型的以太网数据的协议。源mac就是本机mac,目的mac根据上面IP确定的转发端口来决定(基于mac学习完成,ARP查找)
6.数据到达物理层,物理层将数据报转换成光电信号或者电信号进行传输;
7.首先传输到下一台路由器上,路由器进行解析和分用(解析到传输层)NAT 路由选择 ,继续查路由表,把数据再次封装的,往下一个路由器设备上转发(在这里封装和分用和上边是一样的)
8.中间会经过若干个路由器转发的过程,最终到达目的服务器;
9.服务器就会进行分用。物理层把光电信号转成二进制bit流,交给数据链路层;
10.数据链路层从以太网数据报的首部找到MAC地址判断是否为发给自己的包,如果不是发给自己的数据则丢掉。如果是就解析出其中的IP数据报交给网络层,但是如果是无法识别的协议类型也会丢掉。
11.网络层收到数据报,同样进行解析判断自己是不是首部中的目标IP,如果是则接收数据包并查找上一层的协议类型,如果是TCP就交给TCP处理如果是UDP就交给UDP处理。网络层可能需要组包(取决于第4步是否分包),组包后将数据交给传输层;
12.传输层TCP收到数据,首先计算校验和保证数据的完整性,然后按照序号检查接收数据,检查端口号确定具体的应用程序 ,将解析出的应用层数据,交给应用程序,返回ACK(确认序号、窗口大小、延时应答、捎带应答)在这里ACK也是一个TCP数据报,也会涉及到一系列的封装和分用过程,如果没有收到ACK就会反复发送。
13.服务器的应用程序读取数据,解析数据获知邮件的收件人信息以及邮件内容。(应用层)
14.主机B给发送端返回一个回执信息。
15.断开连接(四次挥手)
第一次挥手:主机A想分手,发送消息给主机B
第二次挥手:主机B通知主机A已经接受到分手请求,但还没做好分手准备
第三次回收:主机B已经做好分手准备,通知主机A
第四次挥手:主机A发送消息给主机B,确定分手,主机B关闭连接
数据从网卡到应用的过程
假设一个http请求的数据到达网卡,拿数据时如何层层处理并到达应用的呢?
网卡
网卡也叫网络适配器,具有全球唯一的MAC地址。
· 网卡接受光信号或者电信号,然后将其还原成数字信息(0或1)
· 根据FSCS校验数据,判断数据在传输过程是否因为噪音等影响导致信号失真,从而导致数据错误,需要丢掉这种无用的数据包,
· 检查数据包中MAC头部中的接受方的MAC地址,若不是发给自己的,则丢弃数据包;若数据包是发给自己的,则将数字信息保存到网卡内部缓冲区。
- 以上过程都是网卡内部操作,CPU此时还不知道有数据包来了。*
网卡驱动
硬件需要驱动程序来控制,就像计算机需要操作系统一样,而网卡驱动就是CPU控制和使用网卡的程序
网卡处理完数字信号后,接下来的数据接收需要CPU参与,此时网卡通过中断将数据包达到的事件通知给CPU。接着,CPU暂停手头工作,开始用网卡驱动来干活。
从网卡缓冲区读取接收到的数据,将数据包从网卡硬件缓存转移到服务器内存当中。
根据MAC头部的以太类型字段判断协议种类并调用处理该协议的软件(即协议栈)
通常我们接触的以太类型是 IP协议,因此会调用TCP/IP协议栈来处理。
1、网卡驱动程序提取这个帧的全部内容,去掉以太网的帧头,然后向上传递给IP层
2、IP层接收到包已经,继续去掉IP头的内容,然后交给TCP层
3、TCP层根据TCP协议定义的格式,继续解包,read()从socket buffer读取数据,然后传递给应用层
4、应用层根据TCP层传来的数据,按照对应的应用层来分析包
物理网卡收到数据包的处理流程
1、网卡收到数据包
先将电信号或者光信号转换成网卡fifo存储,网卡申请ring buffer的描述,根据描述找到具体的物理地址;物理网卡通过DMA将数据包从fifo队列写入到该物理地址–》skb_buffer.
2、将数据包从网卡硬件缓存读取到服务器内存
这个时候数据包已经被转移到skb_buffer中,因为是DMA写入,内核并没有监控数据包写入情况,这时候NIC触发一个硬中断,每一个硬件中断会对应一个中断号,且指定一个vCPU来处理,如上图vcpu2收到了该硬件中断.
3、通知内核处理
硬件中断的中断处理程序,调用驱动程序完成,启动软中断
硬中断触发的驱动程序会禁用网卡硬中断,其实这时候意思是告诉NIC,再来数据不用触发硬中断了,把数据DMA拷入系统内存即可
硬中断触发的驱动程序会启动软中断,启用软中断目的是将数据包后续处理流程交给软中断慢慢处理,这个时候退出硬件中断了,但是注意和网络有关的硬中断,要等到后续开启硬中断后,才有机会再次被触发
NAPI触发软中断,触发napi系统
消耗ringbuffer指向的skb_buffer
NAPI循环处理ringbuffer数据,处理完成
启动网络硬件中断,有数据来时候就可以继续触发硬件中断,继续通知CPU来消耗数据包.
4、经过TCP/IP协议逐层处理
5、应用程序通过read()从socket buffer读取数据
如何将网卡收到的数据写入到内核内存?
NIC在接收到数据包之后,首先需要将数据同步到内核中,这中间的桥梁是*rx ring buffer。它是由NIC和驱动程序共享的一片区域,*事实上,rx ring buffer存储的并不是实际的packet数据,而是一个描述符,这个描述符指向了它真正的存储地址,具体流程如下:
1、驱动在内存中分配一片缓冲区用来接收数据包,叫做sk_buffer;
2、将上述缓冲区的地址和大小(即接收描述符),加入到rx ring buffer。描述符中的缓冲区地址是DMA使用的物理地址;
3、驱动通知网卡有一个新的描述符;
4、网卡从rx ring buffer中取出描述符,从而获知缓冲区的地址和大小;
5、网卡收到新的数据包;
6、网卡将新数据包通过DMA直接写到sk_buffer中。
当驱动处理速度跟不上网卡收包速度时,驱动来不及分配缓冲区,NIC接收到的数据包无法及时写到sk_buffer,就会产生堆积,当NIC内部缓冲区写满后,就会丢弃部分数据,引起丢包。这部分丢包为rx_fifo_errors,在 /proc/net/dev中体现为fifo字段增长,在ifconfig中体现为overruns指标增长。