0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

tcp网络协议栈的三个阶段包括哪些

OSC开源社区 来源:OSC开源社区 2023-08-08 10:18 次阅读

一、TCP 网络开发 API

TCP,全称传输控制协议(Transmission Control Protocol),是一种面向连接的、可靠的、基于字节流的传输层通信协议。

1.1、TCP 服务器调用的 API

#include  /* See NOTES */

#include 

// 1

int socket(int domain, int type, int protocol);

// 2

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 3

int listen(int sockfd, int backlog);

// 4

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

// 5

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

// 6

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

// 7

int close(int fd);

// 8

int shutdown(int sockfd, int how);

1.2、TCP 客户端调用的 API

#include  /* See NOTES */

#include 

// 1

int socket(int domain, int type, int protocol);

// 2

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 3

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 4

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

// 5

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

// 6

int close(int fd);

// 7

int shutdown(int sockfd, int how);

1.3、API 函数的作用

(1)int socket(int domain, int type, int protocol) 在文件系统中分配一个 fd,并创建 TCB 数据结构。 (2)int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) 为 TCP 的 socket 绑定本地 IP 地址和端口。 (3)int listen(int sockfd, int backlog) 将 TCP 置于 LISTEN 状态。 (4)int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) 从全连接队列中取出一个节点,并分配一个 fd。 (5)ssize_t recv(int sockfd, void *buf, size_t len, int flags) 在对应 fd 中,从读缓冲区中拷贝出数据。 (6)ssize_t send(int sockfd, const void *buf, size_t len, int flags) 把 fd 对应的 TCB 数据拷贝到写缓冲区中。 (7)int close(int fd) 准备一个 FIN 包,放到写缓冲区,是否 fd。 (8)int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) 准备一个 SYN 包,交给协议栈发送出去,等待三次握手完成后才返回。

二、TCP 的三个阶段

2.1 TCP 建立连接

TCP 连接的建立主要依靠 socket ()、bind ()、listen ()、connect ()、accept () 这几个函数。

2.1.1、TCP 的三次握手

示意图: 6bbf60ae-3514-11ee-9e74-dac502259ad0.png 三次握手在 kernel 协议栈中进行,那么三次握手是在哪几个函数中发送的呢? 第一次,由 connect () 函数触发 发起握手,也就是发送 syn 包到服务端; 第二次,在 listen () 之后 accept () 之前,服务器接收到 syn 包后发送 syn&&ack 包到客户端; 第三次,客户端发送 ack 包到服务端完成连接的建立。 TCP 报头:

0 |1 |2 |3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-------------------------------+-------------------------------+

| Source Port | Destination Port |

+---------------------------------------------------------------+

| Sequence Number |

+---------------------------------------------------------------+

| Acknowledgment Number |

+-------+-----------+-+-+-+-+-+-+-------------------------------+

| Header| Reserve |U|A|P|R|S|F| Window |

| Length| |R|C|S|S|Y|I| |

| | |G|K|H|T|N|N| |

+-------------------------------+-------------------------------+

| Checksum | Urgent Pointer |

+---------------------------------------------------------------+

| Option |

+---------------------------------------------------------------+

| Data |

| ... |

+---------------------------------------------------------------+

SYN:即 synchronous,同步。

ACK:即 acknowledgement,确认。

PSH:即 push,推送。

FIN :即 finish,结束。

RST:即 reset,重置。

URG:即 urgent,紧急。

Sequence Number:是数据包本身第一个字节的序列号。

Acknowledge Number:是期望对方继续发送的那个确认数据包的序列号其值一般为接收到的 Sequence Number 加 1。

从报文中可以看出,SYN 包最重要的是将 SYN 位设为 1,设置 Sequence Number;ACK 包最重要的是将 ACK 位设为 1,设置 Acknowledgment Number。 半连接队列和全连接队列: 在三次握手中,Linux kener 协议栈会维护两个队列:半连接队列和全连接队列。 半连接队列(也叫 SYN 队列):半连接队列在第一握手中,当客户端发送 SYN 包到服务端时,服务端的半连接队列会加入一个节点,表示此连接处于半连接状态。 全连接队列(也叫 ACCEPT 队列):全连接队列在第三握手中,当客户端发送 ACK 包到服务端时,服务端会检查半连接队列中是否存在此连接节点(通过五元组进行查找),如果存在就将此连接节点加入全连接队列中;否则将抛弃此连接。 accpt () 函数在三次握手完成后,从全连接队列中取出连接节点,为节点分配 socket fd,返回到用户态。 那么,accept () 函数如何知道全连接队列中有节点呢? 当三次握手完成后,全连接队列创建节点的同时会释放一个有连接接入的信号(single 或信号量),这个信号决定了 accept () 函数是否可以从全连接队列中取节点;也决定 epoll 等 IO 多路复用器能不能检查这个连接 fd 是否可读。 在阻塞模式下,accept () 函数一直等待信号,直到全连接队列中有节点才返回。 在非阻塞模式下,全连接队列为空 accept () 函数就返回 - 1,否则返回 socket fd。 在 listen () 函数有,有一个 backlog 参数,这个参数表示的是全连接队列的大小还是半连接队列的大小呢? 随着 TCP 协议的不断迭代,backlog 参数在不同的版本中代表的含义也不相同;它可以是半连接队列大小,也可以是全连接队列大小,也可以是半连接队列 + 全连接队列的大小总和。不过,效果不会有太大差异。目前版本中主要表示全连接队列的大小。 DDOS 攻击: 根据三次握手原理,产生一种对服务器的攻击方式:DDOS 攻击。所谓 DDOS 攻击,就是客户端伪造一些不存在的 IP,一直发送 SYN 包,使服务器的半连接队列不断增大,当半连接队列的大小达到极限时,造成网络阻塞就会导致服务器无法再接受连接,从而使服务器奔溃。

2.1.2、TCP 状态转换

TCP 状态转换图: 6bef421a-3514-11ee-9e74-dac502259ad0.png (1)从状态转换图看出,LISTEN 状态可以通过发送 SYN 和数据转换到 SYN_SEND 状态;也就是 LISTEN 状态可以发送数据。 (2)SYN_SEND 状态可以收到 SYN,并发送 SYN 和 ACK 转换到 SYN_RECV 状态;也就是两个设备可以互发 SYN 包,建立连接。

2.2 TCP 传输数据

TCP 传输数据主要依靠 send () 和 recv () 两个函数。 使用 send () 函数发送数据时,返回正数不一定代表发送成功。因为 send () 函数仅仅只是将数据拷贝到协议栈的写缓冲区,由协议栈发送;发送过程中会经过 N 个网关,可能存在丢包或链路断开导致未能发送到目的地。如果要知道数据是否发送成功,需要加上确认机制(ACK)。

2.2.1、传输控制块 TCB

为了保证数据能正确分发,TCP 使用一种 TCB(传输控制块)的数据结构,把发送给不同设备的数据封装起来。这个 TCB 会存在整个 TCP 周期,知道断开连接。 一个 TCB 数据块包含数据发送双方对应的 socket 信息以及拥有存放数据的缓冲区。建立连接连接发送数据之前,通信双方必须做一个准备工作:分配内存建立 TCB 数据块。当双方准备好自己的 socket 和 TCB 数据结构后,就可以进入 “三次握手” 建立连接。

2.2.2、TCP 分包

TCP 分包就是要传输的数据很大,超出发送缓存区剩余空间,将会进行分包;待发送的数据大于最大报文长度,TCP 在传输前将进行分包。 分包在应用程序的处理一般是发送循环 send (),接收方循环 recv ()。

2.2.3、TCP 粘包及解决方案

TCP 粘包就是发送方发送的若干数据包到接收方接收时粘成一个包,从接收缓冲区看就是后数据包的头紧接着前数据包的尾。 常见解决方案: (1)(推荐)应用层协议头前面添加包长度。分两次接收数据;第一次先接收包的长度,然后根据包的长度一次性读取或循环读取数据。 例如:

// ...

ssize count=0;

ssize size=0;

while(countlength)

{

size=recv(fd,buffer,buffersize,0);

count+=size;

}

// ...

(2)为每个包添加分隔符。在数据末尾添加分隔符,这会导致解数据可能需要有合包操作;因为分割数据包后,需要记录后一个数据包,用于与该包后面部分数据进行合并。

6c4775ac-3514-11ee-9e74-dac502259ad0.png

2.3 TCP 四次挥手

断开连接是比建立连接和传输数据还复杂的一个过程,断开连接主要分为主动关闭和被动关闭两种。

四次挥手示意图:

6c74356a-3514-11ee-9e74-dac502259ad0.png

需要注意的是,调用 close () 不是立即完成断开,而是关闭了数据传输,进入了四次挥手阶段,TCB 数据结构还没有释放。四次挥手结束才真正把 TCB 释放。

根据四次挥手流程,可以思考一些问题:

(1)传输数据过程中,网线断了之后立刻连接,TCP 如何知道?

网线掉线网卡会停止供电,再次连接后网卡恢复供电,网卡服务重启,网络连接重连。应用程序设计通过心跳包检测

(2)服务器如何知道客户端是否宕机?

一样需要通过心跳包机制来检测。

(3)服务器如何甄别网络阻塞和宕机?

服务器发送心跳包时,不仅仅发一次,而是要发送多次的;如果是网络阻塞,那么在一定时间内一定有回复信息;如果是宕机,无论多长时间都没有客户端的回复。

(4)如果出现大量的 CLOSING 状态,如何处理?

出现大量 CLOSING 状态,基本上业务上要处理的逻辑过多,导致一直在 CLOSING 状态;可以使用异步,将网络层和业务层分离,单独处理。

(5)四次挥手中,为什么存在 TIME_WAIT 状态?

防止没有 LAST_ACK 或 LAST_ACK 丢失,导致一直重发已经不存在的 socket。

总结

需要掌握 TCP 三次握手和四次挥手的过程,熟悉 TCP 状态转换。清楚什么是 SYN 包和 ACK 包。

(1)三次握手是 由客户端发起 SYN,服务端收到 SYN 后发送 SYN 和 ACK,客户端回复 ACK;完成连接的建立。

(2)断开连接主要有主动断开和被动断开。

(3)四次挥手是 由发起方调用 close (),同时发送 FIN 包;接收端接收到 FIN 包返回 ACK 包,接收端发送 FIN 包;发起方接收到 FIN 包返回 ACK 包;完成断开。

(4)理解 TCP 的状态转换图。LISTEN 状态到 SYN_RCVD 状态和 SYN_SEND 状态,如何进入 ESTABLISHED 状态;四次挥手 FIN_WAIT_1、FIN_WAIT_2、TIME_WAIT、CLOSING 直接的转换,CLOSE_WAIT 和 LAST_ACK 的处理等。

(5)理解 API 的底层原理,以及全连接队列和半连接队列。

(6)TCP 的分包场景以及 TCP 粘包的处理方式。

TCP 通信完整过程:

6c9d40c2-3514-11ee-9e74-dac502259ad0.png


责任编辑:彭菁

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6800

    浏览量

    88733
  • 网络协议
    +关注

    关注

    3

    文章

    262

    浏览量

    21493
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1347

    浏览量

    78925
  • 端口
    +关注

    关注

    4

    文章

    946

    浏览量

    31981

原文标题:详解TCP网络协议栈的工作原理

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    全硬件TCP/IP协议学习笔记(第四天:全硬件TCP/IP协议模块学习)

    做了许多天的网络协议学习,懵懵懂懂了解了点,索性打开说明书开始模块的学习 之前天的学习都是在协议上,今天的学习进入以太网接入方案。 PS
    的头像 发表于 12-18 10:27 8709次阅读
    全硬件<b class='flag-5'>TCP</b>/IP<b class='flag-5'>协议</b><b class='flag-5'>栈</b>学习笔记(第四天:全硬件<b class='flag-5'>TCP</b>/IP<b class='flag-5'>协议</b>模块学习)

    通信网络协议之UDP协议技术解析

    在通常的网络协议中,TCP/IP协议是一常见的
    发表于 02-01 11:00 854次阅读
    通信<b class='flag-5'>网络</b><b class='flag-5'>协议</b><b class='flag-5'>栈</b>之UDP<b class='flag-5'>协议</b>技术解析

    协议介绍--TCP/IP

    的利用率高。且CPU的占用率低。10)本协议支持外网,运行时需要通过ICS服务器与局域网外部网络进行数据通讯。运行时需要设置相关的网关地址,网关地址通过IP层代码进行MAC地址的转换与封装。
    发表于 09-03 15:03

    嵌入式学习的三个阶段详解

      嵌入式可以简单分为硬件与软件,然而其中的知识体系却是异常的庞大,这也是众多新手望而却步的一原因,那究竟要如何才能成为一名嵌入式大咖呢?今天和大家聊一聊嵌入式学习路线,大致分为三个阶段:基础篇
    发表于 07-06 03:33

    LwIP协议开发嵌入式网络种方法有何关系

    LwIP协议开发嵌入式网络种方法分析 轻量级的TCP/IP协议
    发表于 08-05 07:55

    基于LwIP轻量级网络协议实现一TCP协议通信的例程

    1、基于LwIP轻量级网络协议实现一TCP协议通信的例程硬件准备一块 BL706 ETH 开
    发表于 06-29 17:58

    TCP/IP协议之路由器简要分析

    TCP/IP协议中,在封装报文时就相当于是压操作,而在报文解析过程中,则是一的过程,在封装是最先被压进
    发表于 10-10 11:46 1次下载

    MPLAB® Harmony TCP/IP协议

    本视频将介绍MPLAB® Harmony嵌入式网络解决方案。MPLAB Harmony提供免费的TCP/IP协议,可以处理物理网络端口和用
    的头像 发表于 06-07 13:46 3234次阅读
    MPLAB® Harmony <b class='flag-5'>TCP</b>/IP<b class='flag-5'>协议</b><b class='flag-5'>栈</b>

    理解TCP/IP协议遇到的三个疑问解答

    虽然国际标准化组织制定了这样一网络协议的模型,但是实际上互联网通讯使用的网络协议TCP/IP
    的头像 发表于 10-22 14:40 2227次阅读

    Microchip TCP/IP精简协议

    本应用笔记描述 Microchip 传输控制协议 / 互联网协议TCP/IP)精简协议库的结构和接口,并提供部分简单的演示应用。实现
    发表于 04-01 15:36 17次下载
    Microchip <b class='flag-5'>TCP</b>/IP精简<b class='flag-5'>协议</b><b class='flag-5'>栈</b>

    Microchip TCP/IP协议

    。感兴趣的开发人员可以很容易找到许多 Microchip 产品的商业和非商业的TCP/IP 实现方案。本应用笔记详细说明了 Microchip 公司自己免费提供的 TCP/IP 协议
    发表于 04-02 14:28 22次下载
    Microchip <b class='flag-5'>TCP</b>/IP<b class='flag-5'>协议</b><b class='flag-5'>栈</b>

    Linux网络技术中最核心的部分--TCP/IP协议

    今天给大家介绍Linux网络技术中最核心的部分--TCP/IP协议 。 我们先看一下抽象的网络协议
    的头像 发表于 06-29 15:14 2312次阅读

    到底什么是TCP/IP协议,看完这篇你就明白!

    一谈到TCP/IP协议,相信不少小白都处于暴躁的边缘,只懂其一不知其二。没关系,看完这篇你就知道啦!我们先简单了解下TCP/IP协议,该
    的头像 发表于 12-09 15:21 1374次阅读
    到底什么是<b class='flag-5'>TCP</b>/IP<b class='flag-5'>协议</b><b class='flag-5'>栈</b>,看完这篇你就明白!

    tcpip协议是什么?tcpip协议有哪些协议?tcpip协议中报文封装和解封装过程

    tcpip协议是什么? TCP/IP协议是计算机网络中使用的最常见的
    的头像 发表于 08-01 17:51 8137次阅读
    tcpip<b class='flag-5'>协议</b><b class='flag-5'>栈</b>是什么?tcpip<b class='flag-5'>协议</b><b class='flag-5'>栈</b>有哪些<b class='flag-5'>协议</b>?tcpip<b class='flag-5'>协议</b><b class='flag-5'>栈</b>中报文封装和解封装过程

    Linux网络协议的实现

    网络协议是操作系统核心的一重要组成部分,负责管理网络通信中的数据包处理。在 Linux 操作系统中,
    的头像 发表于 09-10 09:51 233次阅读
    Linux<b class='flag-5'>网络</b><b class='flag-5'>协议</b><b class='flag-5'>栈</b>的实现