TCP数据结构
TCP报文封装
IP协议
TCP协议
tcp_hdr
PACK_STRUCT_BEGIN
struct tcp_hdr {
PACK_STRUCT_FIELD(u16_t src);
PACK_STRUCT_FIELD(u16_t dest);
PACK_STRUCT_FIELD(u32_t seqno);
PACK_STRUCT_FIELD(u32_t ackno);
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
PACK_STRUCT_FIELD(u16_t wnd);
PACK_STRUCT_FIELD(u16_t chksum);
PACK_STRUCT_FIELD(u16_t urgp);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
TCP状态机封装
enum tcp_state {
CLOSED = 0,
LISTEN = 1,
SYN_SENT = 2,
SYN_RCVD = 3,
ESTABLISHED = 4,
FIN_WAIT_1 = 5,
FIN_WAIT_2 = 6,
CLOSE_WAIT = 7,
CLOSING = 8,
LAST_ACK = 9,
TIME_WAIT = 10
};
TCP协议控制块
IP_PCB
/** This is the common part of all PCB types. It needs to be at the
beginning of a PCB type definition. It is located here so that
changes to this common part are made in one location instead of
having to change all PCB structs. */
#define IP_PCB \
/* ip addresses in network byte order */ \
ip_addr_t local_ip; \
ip_addr_t remote_ip; \
/* Socket options */ \
u8_t so_options; \
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
u8_t ttl \
/* link layer address resolution hint */ \
IP_PCB_ADDRHINT
TCP_PCB_COMMON
/**
* members common to struct tcp_pcb and struct tcp_listen_pcb
lwip tcp协议控制块非常大,就导致我在监听的时候,不需要这么多,但是又需要其中一部分,就把公共的部分提取出来
*/
#define TCP_PCB_COMMON(type) \
type *next; /* TCP 协议控制块的链表指针 */ \
void *callback_arg; \
enum tcp_state state; /* TCP 状态机 */ \
u8_t prio; \
/* 本地端口号 */ \
u16_t local_port
tcp_pcb_listen
/** the TCP protocol control block for listening pcbs */
struct tcp_pcb_listen {
/** Common members of all PCB types */
IP_PCB;
/** Protocol specific PCB members */
TCP_PCB_COMMON(struct tcp_pcb_listen);
#if LWIP_CALLBACK_API
/* 这是监听的协议控制块,当有客户端连接的时候,需要有个回调函数进行处理 */
tcp_accept_fn accept;
#endif /* LWIP_CALLBACK_API */
#if TCP_LISTEN_BACKLOG
//可同时监听的TCP最大连接数
u8_t backlog;
//已经接入,还未处理的连接数
u8_t accepts_pending;
#endif /* TCP_LISTEN_BACKLOG */
};
tcp_pcb
/** the TCP protocol control block */
struct tcp_pcb {
/** common PCB members */
IP_PCB;
/** protocol specific PCB members */
TCP_PCB_COMMON(struct tcp_pcb);
/* 目标端口号 */
u16_t remote_port;
//tcp协议处理时,定义一些tcp的标志
tcpflags_t flags;
#define TF_ACK_DELAY 0x01U /* 延时应答标志 */
#define TF_ACK_NOW 0x02U /* 立刻应答标志 */
#define TF_INFR 0x04U /* 快速回复标志 */
#define TF_CLOSEPEND 0x08U /* 当FIN包发送失败时,这个标志会置位,同时重发是基于tcp_tmr定时器 */
#define TF_RXCLOSED 0x10U /* 主动关闭接收,此标志位置位 */
#define TF_FIN 0x20U /* 关闭本地连接(发送),此标志位置位 */
#define TF_NODELAY 0x40U /* 关闭Nagle算法的标志位(在TCP通信时,加上缓冲延时算法)*/
#define TF_NAGLEMEMERR 0x80U /* 启动nagle算法标志位*/
#if TCP_LISTEN_BACKLOG
#define TF_BACKLOGPEND 0x0200U /* 当置位时,增大backlog值*/
/* 定时器相关 */
//轮询定时器,在裸机程序中使用,其实就RAW接口
u8_t polltmr, pollinterval;
//最后一次操作pcb时间
u8_t last_timer;
//pcb中的基础定时器
u32_t tmr;
/* tcp接收相关的变量 接收窗口相关的成员变量 */
u32_t rcv_nxt; /* 下个要接收窗口序号*/
tcpwnd_size_t rcv_wnd; /* 接收窗口大小 */
tcpwnd_size_t rcv_ann_wnd; /* 接收窗口大小用于通知目标机 */
u32_t rcv_ann_right_edge; /* 宣布右边沿的窗口 */
/* tcp发送相关的变量 发送窗口相关的成员变量 */
u32_t snd_nxt; /* 下个要发送的窗口序号*/
u32_t snd_wl1, snd_wl2; /* 在下一次窗口更新之前的序号和应答序号 */
u32_t snd_lbb; /* 不能再发送的窗口索引 */
tcpwnd_size_t snd_wnd; /* 程序内部定义的发送窗口 */
tcpwnd_size_t snd_wnd_max; /* 其实就是目标机的介绍窗口*/
tcpwnd_size_t snd_buf; /* 发送缓冲区的大小值*/
/* 重发定时器 (协议交互,握手时) */
s16_t rtime;
s16_t rto; /* retransmission time-out */
u8_t nrtx; /* number of retransmissions */
u16_t mss; /* 最大的段长度*/
/* RTT传输时间,用于优化通讯链路使用*/
u32_t rttest; /* RTT estimate in 500ms ticks */
u32_t rtseq; /* sequence number being timed */
s16_t sa, sv; /* @todo document this */
u32_t lastack; /* 最后一次应答序号 */
/* 阻塞控制的变量 */
tcpwnd_size_t cwnd; //连接窗口
tcpwnd_size_t ssthresh; //慢连接的门限值
/*
实际的TCP数据段内容
*/
struct tcp_seg *unsent; /* 未发送的tcp数据段 */
struct tcp_seg *unacked; /* 发送完毕,单未应答的数据段*/
#if TCP_QUEUE_OOSEQ
struct tcp_seg *ooseq; /* 已经收到的数据段 */
#endif /* TCP_QUEUE_OOSEQ */
struct pbuf *refused_data; /* 已经接收到的数据,并没有让应用层调用 */
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
struct tcp_pcb_listen* listener;
#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
#if LWIP_CALLBACK_API // ----- RAW接口
/* Function to be called when more send buffer space is available. */
tcp_sent_fn sent;
/* Function to be called when (in-sequence) data has arrived. */
tcp_recv_fn recv;
/* Function to be called when a connection has been set up. */
tcp_connected_fn connected;
/* Function which is called periodically. */
tcp_poll_fn poll;
/* Function to be called whenever a fatal error occurs. */
tcp_err_fn errf;
#endif /* LWIP_CALLBACK_API */
/* 心跳检测相关的 */
u32_t keep_idle;
#if LWIP_TCP_KEEPALIVE
u32_t keep_intvl;
u32_t keep_cnt;
#endif /* LWIP_TCP_KEEPALIVE */
/* KEEPALIVE counter */
u8_t keep_cnt_sent;
};