TFTP(使用UDP)
typedef enum{
TFTP_RRQ = 1,
TFTP_WRQ, //读写请求
TFTP_DATA, //数据包
TFTP_ACK, //ACK
TFTP_ERROR //差错包
}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;//已处理的长度
}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
}
举例:
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; //已发送次数
}
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);
};
这个了listen给了个单独的小结构,因为listen时不需要数据交互;
已绑定块进入侦听状态时,是新申请一个小结构tcp_pcb_listen,复制大结构tcp_pcb中的数据,
小结构加入listen链,大结构从bound链删除,之后listen链上的结构并不会被删除(服务器一对多)
关闭连接:
调用tcp_close后,处于closed态的pcb会从tcp_bound_pcbs链上删除,
处于listen态的会从tcp_listen_pcbs链上删除,并回收空间,
其他状态会发FIN,然后走流程