uip_process(u8_tflag)(1)if(flag==UIP_UDP_SEND_CONN),若是则gotoudp_send;不是则向下执行;(2)if(flag==UIP_POLL_REQUEST){if(tcpstateflags==UIP_ESTABLISHED&&!uip_outstanding(uip_connr))如果处于稳定连接状态且没有数据在缓存中等待确认则:{①uip_flags=UIP_POLL;②UIP_APPCALL();③gotoappsend;}gotodrop;}elseif(flag==UIP_TIMER){uip_len=0;uip_slen=0;如果连接处于等待超时关闭状态则增加超时计数器,如果到达超时期限则关闭当前连接tcpstateflags=UIP_CLOSED;if(tcpstateflags!=UIP_CLOSED)如果连接不处于关闭状态{if(uip_outstanding(uip_connr)&&(timer--==0))已经发送的数据包还未接收到对其的ACK,超时计数器减一且超时计数器值为0{①如果到达所设定的重发次数则:1、tcpstateflags=UIP_CLOSED;关闭当前连接2、uip_flags=UIP_TIMEDOUT;通知应用程序超时;3、UIP_APPCALL();4、设置RST+ACK终止连接标志5、gototcp_send_nodata;②没有到达设定的重发次数则重传数据:1、重置重传计数器2、switch(tcpstateflags)根据连接处的不同状态重发不同的数据包caseUIP_SYN_RCVD:gototcp_send_synack;重新发送先前发送的SYN+ACKcaseUIP_SYN_SENT:gototcp_send_syn;重发SYN请求连接caseUIP_ESTABLISHED:uip_flags=UIP_REXMIT;UIP_APPCALL();调用上层应用程序,通知重新生成数据重发gotoapprexmit;进入重发阶段caseUIP_FIN_WAIT_1:caseUIP_CLOSING:caseUIP_LAST_ACK:gototcp_send_finack;重发FIN+ACK关闭连接}elseif(tcpstateflags)==UIP_ESTABLISHED)处于稳定连接状态且上次发送的数据接收到正确的ACK,可以继续发送新数据{①uip_flags=UIP_POLL;询问应用程序是否有数据要发送②UIP_APPCALL();调用应用程序产生数据③gotoappsend;发送数据}}gotodrop;}if(flag==UIP_UDP_TIMER){当前连接的本地端口不为0则{①uip_len=uip_slen=0;②uip_flags=UIP_POLL;询问应用程序是否有数据要发送③UIP_UDP_APPCALL();调用应用程序产生数据④gotoudp_send;}本地端口为0,表明没有建立DUP连接,则{gotodrop;}}(3)检查IP帧头中的IP版本及IP头长度是否符合要求:①不符合:gotodrop;丢弃此包②符合继续向下执行(4)检查目的IP地址是否为本机地址:①不是,gotodrop;丢弃此包②是,向下继续执行(5)if(BUF-proto==UIP_PROTO_TCP)IP上层协议是否为TCP协议①是,gototcp_input;进入TCP数据处理模块②不是,继续向下执行(6)if(BUF-proto==UIP_PROTO_UDP)IP上层协议是否为UDP协议①是,gotoudp_input;进入UDP数据处理模块②不是,继续向下执行(7)if(BUF-proto!=UIP_PROTO_ICMP)不是TCP不是UDP也不是ICMP协议①gotodrop;本机只处理UDP、TCP、ICMP数据包,其它包都将丢弃(8)运行到此处,表明接收到的是ICMP数据包,继续向下执行;———————————————————————————————————————icmp_input:此处为ICMP数据包处理部分,比较简单不做详解。此部分仅仅接收ECHO命令,若接收到别的命令,则将数据包丢弃。若接收到的是ECHO命令则返回包含ECHO_REPLY的ICMP数据包给远方主机,主要是用来响应ping命令。———————————————————————————————————————udp_input:(1)根据要求校验UDP数据(2)在UDP连接列表中寻找接收到的数据包是否属于列表中的连接,若是则gotoudp_found;如果不是则gotodrop;udp_found:(1)接收到数据数设置uip_flags=UIP_NEWDATA;将uip_sappdata,uip_appdata指向接收到的UDP包的数据部分。(2)调用UIP_UDP_APPCALL();使应用程序处理接收到的数据;(3)继续向下执行udp_send:(1)如果uip_slen==0表明没有数据要发送,则直接gotodrop;(2)计算UDP数据包长度,填充UDP、IP帧头中的数据长度及相关选项;(3)根据要求计算校验和;(4)gotoip_send_nolen;发送UDP数据包;———————————————————————————————————————tcp_input:(1)检查TCP校验和,若正确向下继续,若错误则丢弃此包直接返回;(2)在TCP连接列表uip_conns中轮询,检查接收到的TCP数据包是否已经建立连接(通过逐个比较源端口、目的端口和源IP是否与链接列表中的相同)。若找到gotofound;没有找到则检查接收到的TCP数据包中是否含有SYN请求建立连接标志:若没有则gotoreset;发送RST+ACK断开连接;若有则检查uip_listenports监听列表,若TCP数据包目的端口在监听列表中则gotofound_listen;若不在监听列表中则向下执行,进入reset;发送RST+ACK断开连接;reset:(1)接收到的是RST断开连接包,则直接丢包,返回;(2)设置RST+ACK标志,填充适当的TCP帧头;(3)gototcp_send_noconn;发送TCP数据包;found_listen:(1)从链接列表中找出一个空链接或剩余生存时间最短的连接;(2)将找到的链接列表根据接收到的TCP数据包进行初始化;(3)设置TCP状态为UIP_SYN_RCVD;(4)向下执行,发送ACKtcp_send_synack:(1)设置ACK标志(2)向下执行tcp_send_syn:(1)设置SYN标志(2)填充TCP选项中最大报文段长度MSS(3)gototcp_send;found:(1)若接收到的是RST数据包,则将本连接状态置为UIP_CLOSED,uip_flags=UIP_ABORT;,调用UIP_APPCALL()通知应用程序处理连接断开请求。然后丢弃此包,直接返回;(2)检查接收到的数据包中的数据编号是否为自己等在等待的数据编号,若不是则gototcp_send_ack;发送自己期望的数据编号的数据,即请求重传。若是则继续向下;(3)检查接收到的数据包中是否包含ACK,若是则:①更新发送数据序列的编号,使之可以发送后续数据;②计算RTT时间,重新设置RTT时间;③uip_flags=UIP_ACKDATA;表明接收到ACK④uip_connr-len=0;表明等待ACK的数据长度为0,即可以发送其它数据⑤继续向下;若不是:继续向下;TCP状态机switch(tcpstateflags)caseUIP_SYN_RCVD:(1)检查uip_flags==UIP_ACKDATA即是否接收到对自己发送SYN的ACK确认,若是则:①cpstateflags=UIP_ESTABLISHED;/*进入ESTABLISHED状态*/uip_flags=UIP_CONNECTED;/*连接成功*②检查数据包长度是否包含数据部分,若是则uip_flags|=UIP_NEWDATA;③调用UIP_APPCALL()处理刚建立的连接和新接收到数据;⑤gotoappsend;若不是则gotodrop;丢包返回;caseUIP_SYN_SENT:(1)如果接收到ACK且为SYN+ACK则:①检查TCP扩展选项,如果有扩展选项从中取出MSS信息;②tcpstateflags=UIP_ESTABLISHED;进入ESTABLISHED状态③设置接收编号,uip_flags=UIP_CONNECTED|UIP_NEWDATA;调用UIP_APPCALL()处理刚建立的连接和新接收到数据;④gotoappsend;(2)没有接收到ACK且为SYN+ACK则:①uip_flags=UIP_ABORT;终止连接调用UIP_APPCALL();②tcpstateflags=UIP_CLOSED;关闭TCP连接③gotoreset;caseUIP_ESTABLISHED:(1)接收到远方主机的FIN请求:①uip_flags|=UIP_CLOSE;关闭TCP连接②如果接收到的数据包中还包含有数据则uip_flags|=UIP_NEWDATA;③调用UIP_APPCALL()处理刚关闭的连接和新接收到数据;④发送TCP_FIN+TCP_ACK,关闭连接;(2)如果接收到的数据状态为UIP_NEWDATA|UIP_ACKDATA则:①调用UIP_APPCALL();处理接收到的包;②appsend:(1)如果(uip_flags&UIP_ABORT)终止连接则①tcpstateflags=UIP_CLOSED;关闭TCP连接;②发送RST+ACK关闭连接;(2)如果(uip_flags&UIP_CLOSE)正常关闭连接则:①tcpstateflags=UIP_FIN_WAIT_1;进入等待关闭状态②发送FIN+ACK告知对方关闭连接;(3)如果uip_slen0有数据要发送则设置发送数据的长度apprexmit:(1)如果(uip_slen0&&uip_connr-len0)则发送PSH_ACK数据包;(2)如果(uip_flags&UIP_NEWDATA)仅仅是发送ACK,没有数据要发送则发送对接收到数据的ACK;(3)gotodrop;caseUIP_LAST_ACK:(1)如果uip_flags&UIP_ACKDATA接收到对本机发送的FIN的ACK确认则:①tcpstateflags=UIP_CLOSED;将连接置为关闭状态②uip_flags=UIP_CLOSE;调用UIP_APPCALL();通知应用程序连接已经断开;caseUIP_FIN_WAIT_1:(1)此时本机已经关闭连接等待对方关闭连接,如果接收到数据并不处理,仅仅将接收到数据包数目加一;(2)如果接收到FIN请求:①如果(uip_flags&UIP_ACKDATA)接收到对本机发送FIN的确认则将连接状态置为tcpstateflags=UIP_TIME_WAIT;②否则的话则将连接状态置为tcpstateflags=UIP_CLOSING;③uip_flags=UIP_CLOSE;调用UIP_APPCALL();通知应用程序有一方已经关闭连接④gototcp_send_ack;(2)如果(uip_flags&UIP_ACKDATA)仅仅接收到ACK则设置连接状态标志tcpstateflags=UIP_FIN_WAIT_2;进入等待对方关闭阶段(3)如果(uip_len0)表明接收到数据包则gototcp_send_ack;发送对接收到数据的确认ACK;(4)gotodrop;caseUIP_FIN_WAIT_2:(1)此时本机已经关闭连接等待对方关闭连接,如果接收到数据并不处理,仅仅将接收到数据包数目加一;(2)如果接收到对方发送的FIN请求