IP和TCP数据帧头部格式如下图所示。
uIP并没有单独将IP帧拿出来进行单独处理,定义数据结构时直接将IP和TCP部分的头部放在一个结构体uip_tcpip_hdr中:
.Vhl:版本号和首部长度。目前的协议版本号是4,首部长度是以32为单位的IP数据帧头长度,在没有选项时,首部长度字段中的值是5。
·tos:服务类型。uIP中未使用,数值为0。
·len[2]:16位总长度。指的是整个IP数据帧的长度(包括IP帧头)。
·ipid[2]:ipid是一个无符号数,属于同一个报文的分段具有相同的标识符。IP协议每发送一个IP报文,则要把该标识符的值加1,作为下一个报文的标识符。
·Ipoffset:前3位的标志只有低两位有效。
第1位:最终分段标志。若为0,表明该分段是原报文的最后一个分段。
第2位:禁止分段标志。当该位为1时,该报文不能分段。假如此时IP数据包的长度大于网络的MTU值,则根据IP协议丢弃该报文。
ipoffset后13位表示分段偏移,以8B为单位表示当前数据报相对于初始数据报的开头位置。
·Ttl:数据包生存时间。表明数据在进入网络后能够在网络中存留的时间,以秒为单位,最大为255。当为0时该数据包被丢弃,数据报每经过一个路由器时,该值减1。这样,当循环传送的数据包最后总是会被丢弃。
·proto:协议类型。该字段的内容指出IP数据报中数据部分属于哪一种协议(高层协议)。例如0x06为TCP协议,0x01为ICMP协议,0x17为UDP协议等。
·ipchksum:头部校验和。用于保证IP数据帧头部数据的正确性。此校验只是针对IP数据帧头。如果校验失败,数据包将被丢弃。计算方法为,把IP数据帧头作为16位二进制数(校验和本身部分字段设为0),对首部每个16位数进行二进制反码的求和,即得到校验码。接收方收到数据包后,同样对首部每个16位数进行二进制反码的求和(这次包括校验码),如果无误,结果的16位二进制数全为1,否则证明有误。
·SRCipaddr[2]:源IP地址。
·destipaddr[2]:目的IP地址。
以下为TCP数据帧头部各部分说明。
·SRCport:源端口号。
·destport:目的端口号。
·seqno[4]:顺序号,用来标识从TCP源端向TCP目的端发送的数据字节流。
·ackno[4]:确认号,确认号用来指示下一个数据块序列号。
·tcpoffset:包括4位TCP报头长度和6位保留位。4位头长度字段用来说明TCP报文段头部的长度,单位为由32位组成的字的数目。由于TCP选项字段是可选项,所以TCP报文端的头部长度可变。通常这个字段为空,缺省值为5。uIP中初始数值为5,通过与5比较大小来判断是否有选项数据。
·flags:标志。包括6位控制位标志字段。为1表明本字段有效,为0表示无效。
·URG:用来表示报文中的数据已经被发送端的高层软件标志为紧急数据。
·ACK:用来表示确认号的值有效。如果ACK为1,则表示报文段中的确认号有效;否则,报文段中的确认号无效,接收端可以忽略。
·PSH:为1表明接收方应该尽快将这个报文段交给应用层而不用等待缓冲区满。
·RST:用于复位因主机崩溃或其他原因而出现错误的连接,它还可以用于拒绝非法的报文段或拒绝连接请求。为1时表示要重新建立TCP连接。
·SYN:为1时表示连接要与序列号同步。
·FIN:用于释放连接,为1时表示发送端数据已发送完毕。
·wnd[2]:窗口大小。用于数据流量控制。字段中的值表示接收端主机可接收多少个数据块。
·tcpchksum:16位校验和。用于校验TCP报文段头部、数据和伪头部之校验和。校验和的校验方法与IP头部校验方法相同。伪头部如下图所示.
·urgp[2]:16位紧急指针。只有当URG标志为1时紧急指针才有效。紧急指针是一个正偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。
·optdata[4]:选项数据。最常见的可选字段是最长报文大小,又称为MSS。每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它指明本端所能接受的最大长度的报文段。
uIP协议栈中使用uip.conn结构体来保存每一个TCP连接的双方IP地址、端口号、顺序号、确认号等。在uIP中定义了一个数组(见uip.c文件中的structuip_connxdatauip_conns[UIP_CONNS])。数组中的每一个元素保存了每一个连接的状态。每一个元素的类型为structuip_conn型,uip_conn结构体定义如下:
uIP中IP、TCP协议的相关函数大部分都是在uip.c中实现。另外uip.c还包括UDP、ICMP协议的相关函数,本节不对其说明,下面主要对lP和TCP协议的相关函数进行简单分析。
uip.C文件中函数并不多,对相关函数简单说明如下。
①voiduip_init(void)函数功能:uIP协议初始化。所有监听的端口置0,所有连接的状态置为CLOSED。
②structuip_conn*uip_connect(u16_t*ripaddr,u16_trport)函数功能:使用TCP协议与远程主机相连。形参分别为IP地址和端口号。
函数入口:ripaddr为要连接的远程主机的IP地址首地址,rport为要连接的远程主机的TCP端口。
函数返回值:如果连接成功,函数的返回值为一个指向建立连接的连接状态的指针,否则返回值为NULL。
程序中,首先寻找本地未使用的端口,然后在uip_conns[UIP_CONNS]数组中搜索每一个元素,寻找当前未使用的连接,将当前建立的连接状态填入;若没有找到,则寻找数组中重发数据时间最多的一个连接状态元素,将将当前建立的连接状态填入,并返回新建立连接的指针。
⑧voiduip_unlisten(u16_tport)函数功能是停止监听指定的TCP连接端口。
④voiduip_listen(u16_tport)函数功能是监听指定的TCP连接端口。
⑤staticvoiduip_add_rcv_nxt(u16_tn)函数功能是将当前连接的下一个要接收的顺序号加n。只是在uip.c文件内有效。
⑥voiduip_process(u8_tflag)这个函数完成TCP处理,是uIP中最重要和复杂的函数。为了节省RAM,函数中使用了goto语句。实际上,uIP为了减少堆栈使用,设置了大量的全局变量,虽然程序可读性差,各模块之间联系复杂,但是对RAM的使用大大减少,这在8位和16位系统中是我们所期盼的。
本函数只有一个形参flag,在uIP中flag有几种取值:UIP_TIMER(值为2)和UIP_DATA(值为1),uip_process函数根据flag判断进行何种操作。
如果flag标志为UIP_TIMER,则对初始顺序序列号iSS(实际上用数组表示的一个32位数)加1,然后判断当前连接的TCP状态,根据不同的状态来实现不同的操作。注意:uip中的应用程序函数也是在uip_process()函数中实现的。uIP自带的一个http服务器,其文件中,如何在uip_process()函数中实现的,说明如下:
本文关键字:暂无联系方式源码-程序,单片机-工控设备 - 源码-程序
上一篇:uIP在51单片机上的移植