微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于STM32的TCP/IP协议栈代码之UDP分析

基于STM32的TCP/IP协议栈代码之UDP分析

时间:11-18 来源:互联网 点击:

端到端的传输单元(在分片之前和重新组装之后) ,分组是指在IP层和链路层之间传送的数据单元。一个分组可以是一个完整的 IP数据报,也可以是IP数据报的一个分片。(这里有如何分片的说明,书里介绍的详细,简而言之,超过MTU就需要分,但是第一片和接下来的片是有区别的:第一个有UDP首部,其他没有,但是可以通过IP的flags来组合起来。下面的图很形象的说明了。)

------------------------------------------以下内容产生于代码及分析--------------------------------------
3. UDP宏定义实现

// ******* UDP *******

#define UDP_HEADER_LEN 8

//源端口位置

#define UDP_SRC_PORT_H_P 0x22

#define UDP_SRC_PORT_L_P 0x23

//目标端口位置

#define UDP_DST_PORT_H_P 0x24

#define UDP_DST_PORT_L_P 0x25

//UDP数据长度位置

#define UDP_LEN_H_P 0x26

#define UDP_LEN_L_P 0x27

//UDP校验和位置

#define UDP_CHECKSUM_H_P 0x28

#define UDP_CHECKSUM_L_P 0x29

//UDP数据起始地址

#define UDP_DATA_P 0x2a

4. UDP函数实现
本TCP/IP协议栈中的UDP实现只一个make_udp_reply_from_request函数——udp服务器,可以响应其他udp的请求。在连接的顺序看来,在stm32板子上面的为服务器,等待pc机客户端的请求,当请求到来的时候,返回由程序员自行设定的响应,如本文中将做出3个响应的例子(当然udp一旦建立之后,就部分客户端和服务器端,地位是对等的,但是认为发起者为clien比较符合认知而已)。
这里说以下输入吧:buf为缓冲区,data为要传输的数据,datalen即为sizeof(data),port即为pc端的udp端口号

void make_udp_reply_from_request(unsigned char *buf, char *data, unsigned int datalen, unsigned int port)
{
unsigned int i = 0, tol_len;
unsigned int ck;
//如前面的ARP和ICMP一样的
make_eth(buf);
// total length field in the IP header must be set:
//如IP Header
tol_len = IP_HEADER_LEN + UDP_HEADER_LEN + datalen;
buf[IP_TOTLEN_H_P] = tol_len >> 8;
buf[IP_TOTLEN_L_P] = tol_len;
//如ICMP
make_ip(buf);
//本地UDP的端口号
buf[UDP_DST_PORT_H_P] = port >> 8;
buf[UDP_DST_PORT_L_P] = port & 0xff;
// source port does not matter and is what the sender used.
// calculte the udp length:最大16bit长度,即65535-14-20-8,但一般会设置的较小,原因么,上文里面讲过。
buf[UDP_LEN_H_P] = datalen >> 8;
buf[UDP_LEN_L_P] = UDP_HEADER_LEN + datalen;
// zero the checksum
buf[UDP_CHECKSUM_H_P] = 0;
buf[UDP_CHECKSUM_L_P] = 0;

// copy the data:
while(i < datalen)
{
buf[UDP_DATA_P + i] = data[i];
i++;
}

//UDP_DEBUG插入此处
//这里的16字节是UDP的伪首部,即IP的源地址-0x1a+目标地址-0x1e(和标准的有差异),
//+UDP首部=4+4+8=16
ck = checksum(&buf[IP_SRC_P], 16 + datalen, 1);
buf[UDP_CHECKSUM_H_P] = ck >> 8;
buf[UDP_CHECKSUM_L_P] = ck & 0xff;
enc28j60PacketSend(UDP_HEADER_LEN + IP_HEADER_LEN + ETH_HEADER_LEN + datalen, buf);
}

5. UDP实验
在有了以上的UDP实现之后,你还需要有UDP的请求进来,如下代码所示:
下面的代码放在一个while(1)或者RTOS进程里面,作为服务器来等待客户端的响应

/*--------------------- udp server start, we listen on udp port 1200=0x4B0 -----------------------------*/
if (buf[IP_PROTO_P]==IP_PROTO_UDP_V&&buf[UDP_DST_PORT_H_P]==4&&buf[UDP_DST_PORT_L_P]==0xb0)
{
//UDP数据长度
udpdatalen=buf[UDP_LEN_H_P];
udpdatalen=udpdatalen<8;
udpdatalen=(udpdatalen+buf[UDP_LEN_L_P])-UDP_HEADER_LEN;
//udpdatalen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
//获取pc端的udp port
pcudpport=buf[UDP_SRC_PORT_H_P]<8 | buf[UDP_SRC_PORT_L_P];
//将udp客户端得到的数据buf写入buf1,因为下面的实验需要输入的信息来做出相应的动作
for(i1=0; i1buf1[i1]=buf[UDP_DATA_P+i1];

make_udp_reply_from_request(buf,buf1,udpdatalen,pcudpport);
}
/*----------------------------------------udp end -----------------------------------------------*/

ps:本实验中板子udp的port为1200,pc机的port为4001
实验部分实现了三个简单的实验:
1.通过串口输出UDP客户端的IP地址及端口号
2.通过串口和UDP输出UDP的输入数据,即USART ECHO和UDP ECHO
3.实现UDP命令控制STM32">STM32板子上面的LED

void make_udp_reply_from_request(unsigned char *buf, char *data, unsigned

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top