• 关于LWIP的一点记录(三)


    TFTP(使用UDP)
    typedef enum{

    TFTP_RRQ = 1,
    TFTP_WRQ,	//读写请求
    TFTP_DATA,	//数据包
    TFTP_ACK,	//ACK
    TFTP_ERROR	//差错包
    
    • 1
    • 2
    • 3
    • 4
    • 5

    }tftp_opcode;
    typedef struct{

    int op;			//操作码tftp_opcode
    char data[512];
    int data_len;	//data有效长度
    u16_t remote_port,block;//block is 序号
    u32_t tot_bytes;//已处理的长度
    
    • 1
    • 2
    • 3
    • 4
    • 5

    }tftp_connection_args;
    udp_new -> udp_bind -> udp_recv … -> udp_disconnect -> udp_remove
    当接收方发现包长度 < 512时,标志结束,清理连接

    TCP相关:
    enum tcp_state{

    CLOSED = 0,
    LISTEN,
    SYS_SENT,	//已发送连接请求
    SYN_RCVD,	//已收到连接请求
    ESTABLISHED,
    FIN_WAIT1,	//本端已关闭连接(发送FIN,等ACK)
    FIN_WAIT2,	//(收到了ACK)
    CLOSE_WAIT,	//(收到FIN,发了ACK)
    CLOSING,	//两边同时收到关闭请求
    LAST_ACK,	//另一端已经关闭的情况下,本端发了FIN,等ACK
    TIME_WAIT	//本端已关闭的情况下,收到FIN,发了ACK,再等2MSL 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    }

    举例:
    client:CLOSED ->

    struct tcp_pcb{ //包括了实现TCP机制的所有参数,简述

    IP_PCB; TCP_PCB_COMMON(tcp_pcb);	//抽取公共部分
    remote_port;
    flags;	//7个标志bit位
    //接收窗口相关
    rcv_nxt;//下一个期望收到的序号
    rcv_wnd,rcv_ann_wnd;//接收窗口,没仔细看区别是啥
    rcv_ann_right_edge;	//窗口右边界的后一个;
    
    tmr;	//记录切换状态时的系统时间
    last_timer;	//上次快定时器处理时间
    polltmr,pollinterval;	//polltmr周期自增,达到pollinterval时调用poll函数
    //超时重传相关
    rtime;	//重传定时器
    mss;	//最大报文长度
    rttest;	//估计RTT用的计时
    rtseq;	//估计RTT用的序号
    sa,sv;	//计算RTO的参数
    rto;	//重发超时时间,rtime超过rto时重传
    nrtx;	//被重发次数
    
    cwnd;	//阻塞窗口(发送方设置)
    ssthresh;//拥塞避免阈值
    //发送窗口相关
    snd_nxt; //下一个将发送的序号
    snd_wnd; //发送窗口(接收方通告)———— 取min(cwnd,snd_wnd)作为有效发送窗口
    lastack;//最大确认号(窗口左边界的前一个)
    dupacks;//lastack被重复收到的次数
    
    snd_wl1,snd_wl2;	//对应上一次的seqno和ackno
    snd_wnd_max;
    acked;
    //用于记录缓冲区相关
    snd_lbb;//下一个将要缓冲的序号
    snd_buf;//可使用发送缓冲区大小(用于判断要发的数据能不能放得下)
    snd_queuelen;//缓冲区已占pbuf数(不能超过允许挂的pbuf总数)
    
    //控制块(本连接)维护的3个缓冲队列	
    struct tcp_seg * unsent,unacked,ooseq;//未发送,已发送未确认,无序
    
    struct pbuf * refused_data;
    
    //回调函数
    sent,recv,connected,poll,err;//发送,接收,连接,周期,错误
    
    //0窗口探查
    persist_cnt;	//探查定时器
    persist_backoff;//已探查个数
    
    //保活
    keep_idle;		//保活计时器(上限)
    keep_cnt_sent;	//已发送次数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    }

    LWIP给TCP搞了4个pcb链(根据状态分类):
    tcp_bound_pcbs:刚创建,绑定完(closed)
    tcp_listen_pcbs:侦听状态
    tcp_active_pcbs:其他状态
    tcp_tw_pcbs:处于TIME_WAIT状态(2MSL后CLOSE)

    接收窗口:可以进入的序号范围,有数据进入时窗口减小,上层取走数据后窗口增加
    侦听的结构:
    struct tcp_pcb_listen{

    IP_PCB;		//之前抽出来的公共部分
    TCP_PCB_COMMON(tcp_pcb_listen);
    
    • 1
    • 2

    };
    这个了listen给了个单独的小结构,因为listen时不需要数据交互;
    已绑定块进入侦听状态时,是新申请一个小结构tcp_pcb_listen,复制大结构tcp_pcb中的数据,
    小结构加入listen链,大结构从bound链删除,之后listen链上的结构并不会被删除(服务器一对多)

    关闭连接:
    调用tcp_close后,处于closed态的pcb会从tcp_bound_pcbs链上删除,
    处于listen态的会从tcp_listen_pcbs链上删除,并回收空间,
    其他状态会发FIN,然后走流程

  • 相关阅读:
    考研人考研魂——英语单词篇(20231009)
    c++ 中的函数指针
    flex布局(学习笔记)
    【Python搜索算法】深度优先搜索(DFS)算法原理详解与应用,示例+代码
    redis的安装和配置
    商人宝:选择服装店收银系统源码需要注意的三个关键点
    Bom浏览器对象模型
    如何在Linux部署Portainer并结合内网穿透远程管理本地Docker容器
    [BJDCTF2020]Mark loves cat
    pytorch 实战【以图像处理为例】
  • 原文地址:https://blog.csdn.net/weixin_40852534/article/details/126203224