C/C++编程-TCP/IP协议-LwIP学习手札

LwIP协议栈学习

  • 流程图
    • 整体工作流程
  • 模块分析
    • IP[Internet Protocol]【网际协议】
    • TCP[Transmission Control Protocol]【传输控制协议】
    • ICMP[Internet control message protocol]【Internet控制报文协议】
      • 报文协议格式
    • 内存管理
      • 内存管理策略
        • 动态内存堆分配策略
        • 动态内存池[POOL]分配策略
          • 用到的语法技巧
    • 数据包pbuf
  • 小知识汇总

流程图

以梳理流程图的方式,认识LWIP协议栈的工作流程、和工作原理。

整体工作流程

Created with Raphaël 2.3.0 初始化 轮询阻塞(邮箱) 是否有信息? 上层(发送)下层(接收) yes no

模块分析

一个整体协议也可作为一个模块,既要向下兼容,也要向上兼容。这种兼容无疑要采用“接口”实现。向下要兼容各种硬件、平台的硬件驱动(想想这里的接口实现方式,可以linux驱动模型吧?)。向上也要给应用留出好用的接口。

C/C++编程-TCP/IP协议-LwIP学习手札_第1张图片

IP[Internet Protocol]【网际协议】

TCP[Transmission Control Protocol]【传输控制协议】

ICMP[Internet control message protocol]【Internet控制报文协议】

它是tcp/ip协议簇的一个子协议。是一种面向无连接的“错误侦测与回报机制”的协议。

报文协议格式

ICMP报文包含在IP数据报中,属于IP的一个用户,IP头部就在ICMP报文的前面,所以一个ICMP报文包括IP头部、ICMP头部和ICMP报文。IP头部的Protocol值为1就说明这是一个ICMP报文,ICMP头部中的类型(Type)域用于说明ICMP报文的作用及格式,此外还有一个代码(Code)域用于详细说明某种ICMP报文的类型,所有数据都在ICMP头部后面。这里有一个简洁,扼要的ICMP协议格式ICMP协议格式
在这里插入图片描述C/C++编程-TCP/IP协议-LwIP学习手札_第2张图片
ICMP报文主要有两个功能:查询报文和差错报文

//定义ICMP首部
typedef struct _icmphdr{
  unsigned char i_type; //8位类型
  unsigned char i_code; //8位代码
  unsigned short i_cksum; //16位校验和, 从TYPE开始,直到最后一位用户数据,如果为字节数为奇数则补充一位
  unsigned short i_id ; //识别号(一般用进程号作为识别号), 用于匹配ECHO和ECHO REPLY包
  unsigned short i_seq ; //报文序列号, 用于标记ECHO报文顺序
  unsigned int timestamp; //时间戳
}ICMP_HEADER;

C/C++编程-TCP/IP协议-LwIP学习手札_第3张图片

内存管理

内存管理策略

动态内存堆分配策略

动态内存池[POOL]分配策略

用到的语法技巧
  1. 宏定义
    概念:在编译时,直接替换
    #define MACRO_EXP macro_actual
         表达      作用

分析:
C/C++编程-TCP/IP协议-LwIP学习手札_第4张图片

数据包pbuf

LWIP有一个高效的数据包管理核心,能够兼容各种数据类型的数据,避免在各层之间复制数据的巨大开销。

struct pbuf {
	struct pubf *next;		/* 详见说明【1】 */
	void  *payload;			/* 详见说明【2】 */
	u16_t tot_len;			/* 详见说明【3】 */
	u16_t len;				/* 详见说明【4】 */
	u8_t  type;				/* 详见说明【5】 */
	u8_t  flags;			/* 详见说明【6】 */
	u16_t ref;				/* 详见说明【7】 */
}

说明:
【1】:单向链表,指向下一个puf数据包
【2】:数据指针,指向pbuf数据的起始地址
【3】:包含当前的pbuf和其后的所有pbuf的有效数据长度。
【4】:当前bupf中的有效数据长度。
【5】:当前pbuf的类型。有四种: PBUF_RAM、PBUF_ROM、PBUF_REF、PBUF_POOL。
【6】:当前pbuf的类型。未使用。
【7】:该pbuf被引用的次数。初始化值为1.

  • offset -【8】* :payload用来存储数据的包头的空间,如TCP包头、IP包头。可以是0

说白就是一个二级管理机制:
{包管理头(拆分包管理)} + {包数据头(数据帧管理)} + {数据}

注解:

  1. pbuf 链中第一个 pbuf 的 tot_len 字段表示整个数据包的长度,而最后一个 pbuf 的 tot_len
    字段必和 len 字段相等。
  2. type 之 RAM -> 堆 -> mem_malloc -> {SIZEOF_STRUCT_PBUF + length + offset} -> 结构头和数据区的地址连续的。
  3. type 之 POOL -> memp_malloc(MEMP_PBUF_POOL)
  4. type 之 ROM & REF -> 堆中申请结构头空间 : ROM内 or RAM 内。-> memp_malloc(MEMP_PBUF)
  5. 对于一个数据包,它可能使用上述的任意的 pbuf 类型,很可能的情况是,一大串
    不同类型的 pbufs 连在一起,用以保存一个数据包的数据 。

小知识汇总

  1. 数据包的管理有一个核心的东西,当数据在各层之间传递时,LWIP极力禁止数据的拷贝的工作,因为这样会耗费大量的时间和内存。

你可能感兴趣的:(C/C++编程,嵌入式,tcp/ip,学习,网络)