从网卡到TCP/IP协议栈的数据流转

从网卡开始到TCP/IP协议栈的数据流转

网络请求达到应用程序的处理过程

一个数据包通过网线传输过来,按照网络模型划分,依次需要经过五层处理

TCP协议报文模型.png

当到达网卡之后


数据从网卡到应用程序.png
  1. 数据首先到达网卡,此时是光信号(光纤)或电信号(网线)
  • 网卡首先将其还原成电信号

  • 根据FCS(帧校验序列,Frame check Squence)校验数据,丢弃失真的数据

  • 校验mac地址,不是发送给自己的则丢弃

  • 发送中断信号通知CPU或者DMA

  1. CPU/DMA通过网卡驱动参与数据接收
  • CPU/DMA收到网卡的中断信号后,选择时机进入中断,通过网卡驱动读取拷贝网卡数据到内核缓存区

  • 根据mac头部的以太类型字段判断协议种类并调用处理该协议的协议栈,这里使用TCP/IP协议栈举例

  • IP模块判断数据包是否发送给自己,不是则丢且

  • 判断数据包是否分片(以太网中,一个包的最大长度不能超过1500字节),如果分片则缓存起来等待分片全部到达再还原成数据包

  • 根据IP头部的协议号字段转发给TCP模块处理

  1. TCP模块解析数据
TCP协议报文模型.png
  • TCP模块根据TCP协议还原数据包

  • TCP 根据 标志位FLAGS 识别不同的报文,多个标志位可能同时为1,如:ACK与SYN,表示服务端收到建立连接请求之后的响应

    FLAGS字段标识位 含义
    SYN=1 请求建立连接
    FIN=1 关闭连接
    ACK=1 响应
    PSH=1 有DATA传输
    RST=1 连接被重置
    URG=1 有紧急数据
  • 如果是请求连接的包,首先检查接收方端口号,然后检查有没有与该端口号相同且处于等待连接状态的socket,如果有,则为这个套接字复制一个副本,将发送反IP,端口等必要信息写入套接字,同时分配用于发送缓冲区和接收缓冲区的内存空间

  • 如果是正常数据包,TCP模块数据检查该包对应的socket,然后提取出数据,存放到缓冲区,如果此时socket缓冲区满了,则TCP数据传输阻塞.此时如果应用程序来调用socket的read(),那么数据就可以转交给应用程序,否则数据会一直保存在缓冲区中

  1. 通过Socket与应用程序交换数据

    应用程序不能直接与内核进行IO通信,网络IO通过socket,文件IO通过文件句柄

  • CPU/DMA将数据拷贝到socket缓冲区之后,应用程序通过调用socket的read()方法将数据copy到应用程序进程内存中

  • 如果应用程序是JAVA且使用堆内内存操作,那么还需要将数据从堆外copy到堆内,因为JVM建立了自己的内存模型JMM,不能直接识别堆外内存的数据

TCP三次握手

  1. 什么是连接?

    为了数据的可靠传输,客户端与服务端通信之前,确认对方是否可通信,所做的通信前检查工作.

    当检查完成后,客户端与服务端都会维护一个可通信的状态.

    这就是建立连接的目的,即三次握手需要达成的目标

RFC 793对连接的定义如下:

Connections:

The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream.

The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection.

用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合包括socket,序列号,窗口大小

  • 客户端主动发起连接,发送syn包,进入syn-send状态

  • 服务端检查可建立连接之后响应ack,并同时响应syn,要求客户端确认是否可建立连接,进入syn-rcvd状态

  • 客户端收到ack报文,然后进入estalished状态,初始化socket,分配缓冲区内存

  • 服务端收到ack,进入estalished状态,初始化socket,分配缓冲区内存

  1. 为什么是三次握手,不是两次

    正常情况下,会按照如上步骤走完,但通常情况下,任何一个步骤都可能会异常

    • 节省不必要的资源浪费

      客户端需要确认服务端可连接后,再创建socket并分配内存空间

      服务端需要确认客户端响应了最新的可连接后报文后,再创建socket并分配空间

    • 避免历史连接

      当客户端发送syn报文后,超时没有收到ack报文,那么会再次发送syn报文.旧的报文先与新的报文到达

      客户端收到服务器对旧的syn响应的ack后,根据序列号和超时时间判断,这是服务端响应的历史报文,则发送RST终止连接

      如果是两次握手,那么不能判断是否是历史连接

    • 同步双方初始序列号

      序列号是可靠传输的关键因素

      对于接收方的作用

      • 去除重复的数据

      • 根据序列号按序接收

      • 标识发送出去的数据包中,哪些是已接收的

    为什么不是四次呢?

    TCP建立连接的目的是确认双方建立连接的可靠性检查,三次握手已经达到目的

  2. 建立连接过程中服务器做了什么处理

    服务器用两个队列来维护连接

    一个是syn队列,保存未完成建立连接的队列

    一个是accept队列,保存连接完成的队列


    服务器TCP维护SYN与ACCEPT队列.png
当应用程序调用accept()时,从accept队列中获取一个已建立好连接的socket

也可以通过不同的内核参数,控制syn队列和accept队列的大小,达到优化程序的目的
  1. socket底层流转
    socket TCP 编程(1).png
服务端:

*   创建一个元socket,调用bind()绑定端口

*   调用listen() 告知内核监听此端口是否有连接到来,内核创建syn和accept两个队列。当有连接到来时,内核完成三次握手

*   调用accept阻塞获取完成连接的accept队列新的socket

TCP四次挥手

TCP是全双工的通信协议,客户端与服务端都可以主动断开连接,区分为主动关闭连接的一方,被动关闭连接的一方

  • 客户端发送FIN报文,进入fin-wait状态

  • 服务端响应ack,进入close-wait状态

    客户端收到ack报文,进入 fin-wait2状态

  • 服务器处理完数据,发送fin报文,进入last-ack状态

  • 客户端收到fin报文,响应ack,进入time-wait状态

    服务器收到ack报文,连接关闭,进入close状态

  • 客户端在经过2MSL(maximum segment lifetime 报文最大生存空间) 一段时间后,自动进入close状态

在四次挥手过程中,当服务端接收到客户端断开连接的fin报文后,需要等待数据处理的完成,所以先回复ack,然后再发送fin报文。因此需要四次

为什么客户端收到fin返回ack不直接进入close状态,而是进入time-wait状态呢?

  • 为了帮助被被动关闭的一方能够正确的关闭。如果ack报文在网络中丢失,那么服务端会重发fin报文,客户端处于time-wait状态,仍然可以响应ack

  • 防止收到旧的四元组的包,如果客户端直接关闭连接,使用相同的四元组新建连接,那么可能收到旧连接的数据报文

TCP数据传输

TCP是一个可靠传输协议,通过序列号,确认应答,重发控制,连接管理以及窗口控制等机制实现可靠性传输

  1. 重传机制

    发送方发送一个数据,当接收方接收到后,会回应一个ack,表示报文已经收到。

    TCP使用SACK和D-SACK的方式,首先发送方发送一个完整数据序号列表,接收方接收数据时,根据数据列表确定哪些没有收到,需要客户端再次发送

  2. 滑动窗口

    TCP如果每次只发送一个数据包,那么会导致效率非常低,因此使用一个滑动窗口来发送数据

    窗口指无需等待确认应答,而可以继续发送数据的最大值

  3. 流量控制

    发送方与接收方的速率并不相同,因此,需要协商一个双方都能接收的速度

    TCP提供一种机制可以让发送方和接收方的时机接收能力控制发送的数据量,这就是流量控制

    具体是指:当发送端发送一个滑动窗口的数据,接收方根据处理能力,调整滑动窗口的大小,返回给发送端

  4. 拥塞控制

    当数据传输受网络带宽等其它影响,接收方不能及时的返回应答

    因此发送方根据超时量去主动调整滑动窗口的大小,这就是拥塞控制

UDP

UDP报文(1).png

UDP不提供复杂的控制机制,利用ip提供无连接的通信服务

UDP传输时,只管发送,并不考虑接收端是否已经接收到,因此存在丢包的可能

应用场景:直播,DNS服务

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,825评论 6 546
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,814评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,980评论 0 384
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 64,064评论 1 319
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,779评论 6 414
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 56,109评论 1 330
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 44,099评论 3 450
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,287评论 0 291
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,799评论 1 338
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,515评论 3 361
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,750评论 1 375
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,221评论 5 365
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,933评论 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,327评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,667评论 1 296
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,492评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,703评论 2 380

推荐阅读更多精彩内容