STM32以太网程序解析四
2018-03-06 16:35阅读:
TCP/IP/ARP/ICMP首部分析
STM32以太网程序解析一
STM32以太网程序解析二
STM32以太网程序解析三
STM32以太网程序解析四
---------------------------------------------------------------------------------------------------------------------------
函数先清空校验和,然后设置IP首部标志总第0x14字节中不分段位为1,表示不允许分段,段偏移量为0,设置生存时间为64跳。最后计算校验和,填充校验和。校验和计算函数的计算方法我们这里不做介绍。
make_ip函数执行完成后,将ICMP相应的包类型修改为回射应答。然后填写IP校验和,最后通过ENC28J60将数据发送出去。
48行处理完ICMP回射应答后,通过continue语句重新接收数据包做处理。
如果不是ICMP包41行if函数不成立,程序继续往下执行。
52行if语句判断是否TCP包,判断的依据为查看IP首部(总第0x17字节)的协议代码是否为6(6代表TCP),并且TCP首部目的端口(总第0x24字节和0x25字节)是否与服务器的port相同,如果不正确则说明不是TCP包,程序继续往下执行。如果两者都正确说明是TCP包,if条件成立,执行if里面的函数
57行if语句判断TCP包类型,判断方法是对TCP首部中的6个标识位进行识别(总第0x2F字节的后6位)判断SYN位是否置位,如果没有置位则if条件不成立继续往下执行,如果SYN位置位说明TCP包是一个连接请求TCP包。
60行对连接请求TCP包做应答,该行函数的内部操作是
1.
void
make_tcp_synack_from_syn(unsigned
char *buf)
2. {
3.
unsigned
int ck;
4.
5.
//
填写包的目的MAC地址以及源MAC地址
6.
make_eth(buf);
7.
8.
//
计算包长度=IP头(20)+TCP头(24)
9.
buf[IP_TOTLEN_H_P]=0;
10.
buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4;
11.
12.
//
填写包的目的IP地址以及源IP地址
13.
make_ip(buf);
14.
15.
buf[TCP_FLAGS_P]=TCP_FLAGS_SYNACK_V;
16.
17.
// 填写TCP头
18.
make_tcphead(buf,1,1,0);
19.
20.
// 计算校验和
长度=8 (开始于ip.src) + TCP头长(20) +
可选选项(4字节,mss)
21.
ck=checksum(&buf[IP_SRC_P],
8+TCP_HEADER_LEN_PLAIN+4,2);
22.
buf[TCP_CHECKSUM_H_P]=ck>>8;
23.
buf[TCP_CHECKSUM_L_P]=ck& 0xff;
24.
25.
printf('\r神舟III号[%d.%d.%d.%d]发送SYN包响应',ipaddr[0],ipaddr[1],ipaddr[2],ipaddr[3]);
26.
27.
enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4+ETH_HEADER_LEN,buf);
28. }
首先是make_eth,然后计算包裹长度填入IP首部的包裹长度(总第0x10字节和0x11字节),接着make_ip,接着修改TCP首部中6个标志为中的ACK与SYN位置位,表示同步确认。接着调用make_tcphead函数,该函数的内部操作:'首先将TCP首部的源端口与目的端口互相对调,然后设置数据序号与确认序号,接着设置选项字节,最后更新偏移位。'接着计算校验和填充TCP首部中的校验和,最后通过ENC28J60将数据发送出去。
61行,发送同步请求应答TCP包后,continue语句重新接收数据包做处理。
65行通过if语句判断TCP包类型,判断方法是对TCP首部中的6个标识位进行识别(总第0x2F字节的后6位)判断ACK位是否置位,如果没有置位则if条件不成立继续往下执行,如果ACK位置位说明TCP包是一个TCP确认包。接下来就解析这个包数据
70行初始化数据格式,并获取TCP包,数据区长度。数据区长度保存在全局变量info_data_len中
71行用于获取数据区首地址在buf中的位置。其结果返回到dat_p变量。
74行判断是否为一个无数据的TCP包,如果有数据则不进入if内部,程序继续往下进行,如果是无数据的TCP包,则在if内部做继续判断
77行在上一个if内部继续做判断通过6个bit的标志位判断是否为要求释放连接(终止)的TCP包。如果不是则,continue继续等待重新接收数据包,如果是执行81行函数
81行函数对要求释放连接(终止)的TCP包做应答,它内部到操作函数是
1.
void
make_tcp_ack_from_any(unsigned
char *buf)
2. {
3.
unsigned
int j;
4.
5.
//
填写包的目的MAC地址以及源MAC地址
6.
make_eth(buf);
7.
8.
//
填充包的类型为ack响应包
9.
buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V;
10.
11.
//
判断接收的TCP包内是否有数据
12.
if
(info_data_len==0)
13.
{
14.
make_tcphead(buf,1,0,1);
15.
}
16.
else
17.
{
18.
make_tcphead(buf,info_data_len,0,1);
19.
}
20.
21.
//
设置IP包头中总长度:长度=IP头(20)+TCP头(20(不包括选项字节))
22.
j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN;
23.