基于LWIP的UDP实例
本工程硬件基于STM32F429+LAN8720A外设,使用RMII通信接口。工程由STM32CUBEMX直接生成。代码主要使用的是ST官方例程。
1. 服务器端
//定义端口号
#define UDP_SERVER_PORT 7 /* define the UDP local connection port */
#define UDP_CLIENT_PORT 7 /* define the UDP remote connection port */
//声明接收数据回调函数,在初始化函数中指定
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
//UDP服务器端初始化函数
void udp_echoserver_init(void)
{
struct udp_pcb *upcb;
err_t err;
/* Create a new UDP control block */
upcb = udp_new(); //创建一个新的UDP控制块
if (upcb)
{
/* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT); //绑定本地IP地址及端口
if(err == ERR_OK)
{
/* Set a receive callback for the upcb */
udp_recv(upcb, udp_echoserver_receive_callback, NULL); //注册接收数据回调函数
}
else
{
udp_remove(upcb);
}
}
}
//服务器端接收数据回调函数
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
/* Tell the client that we have accepted it */
udp_sendto(upcb, p,addr,port); //回显数据
/* Free the p buffer */
pbuf_free(p);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
在main.c文件中,在LWIP初始化之后,增加服务器端初始化函数,即可实现服务器端功能,实现数据回显功能。
udp_echoserver_init();
- 1
2.客户端
//接收数据回调函数声明
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
u8_t data[100]={0x00}; //数据buffer初始化
__IO uint32_t message_count = 0;
struct udp_pcb *upcb; //UDP控制块初始化
//UDP客户端连接函数
void udp_echoclient_connect(void)
{
ip_addr_t DestIPaddr;
err_t err;
/*assign destination IP address */
IP4_ADDR( &DestIPaddr, 192, 168, 1, 103 ); //设置服务器端的IP地址
/* Create a new UDP control block */
upcb = udp_new(); //创建一个新的UDP控制块
if (upcb!=NULL)
{
/* configure destination IP address and port */
err= udp_connect(upcb, &DestIPaddr, 7); //服务器端地址、端口配置
if (err == ERR_OK)
{
printf("local port is %d\r\n",upcb->local_port);
/* Set a receive callback for the upcb */
udp_recv(upcb, udp_receive_callback, NULL); //注册回调函数
udp_echoclient_send(); //**数据发送,第一次连接时客户端发送数据至服务器端,发送函数中会遍历查找源IP地址的配置,如果源IP地址未配置,则数据发送失败。该处出现的问题在后面总结中提到了**
}
}
}
//客户端数据发送函数
void udp_echoclient_send(void)
{
struct pbuf *p;
sprintf((char*)data, "sending udp client message %d", (int)message_count);
/* allocate pbuf from pool*/
p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);
printf("test1\r\n");
if (p != NULL)
{
printf("test2\r\n");
/* copy data to pbuf */
pbuf_take(p, (char*)data, strlen((char*)data));
/* send udp data */
udp_send(upcb, p); //发送数据
/* free pbuf */
pbuf_free(p);
}
printf("test3\r\n");
}
//客户端接收数据回调函数
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
/* send udp data */
udp_send(upcb, p); //数据回显
/* free pbuf */
pbuf_free(p);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
在main.c文件中,在LWIP初始化之后,增加客户端初始化函数,即可实现客户端功能,实现数据回显功能。
udp_echoclient_connect();
- 1
3.总结
- 基于STM32CUBEMX工具的便利性,很方便的图形化配置界面,可以直接生成需要的底层驱动代码,本次工程即直接生成了RMII+LWIP代码,主要工作放置在UDP客户端及服务器端代码的处理上。
- 对于生成过程中,我选择了DHCP服务,即自动获取IP地址。本来该方式是随时根据网络环境动态获取IP地址,是很便利的一种方法。但是对于我这个初学者,在使用UDP客户端时,想在配置完服务器端IP、端口号之后,向服务器端发送数据。参考了许多网上的实例都无法实现,后来使用printf打印,发现在此处send数据时,源IP地址为空,造成数据无法正常发送出去,只能在callback回调函数中进行数据发送。后面暂时去掉了DHCP服务,使用自己配置的IP则无此现象。卡了好久,做个记录。
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
</div>
基于LWIP的UDP实例
本工程硬件基于STM32F429+LAN8720A外设,使用RMII通信接口。工程由STM32CUBEMX直接生成。代码主要使用的是ST官方例程。
1. 服务器端
//定义端口号
#define UDP_SERVER_PORT 7 /* define the UDP local connection port */
#define UDP_CLIENT_PORT 7 /* define the UDP remote connection port */
//声明接收数据回调函数,在初始化函数中指定
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
//UDP服务器端初始化函数
void udp_echoserver_init(void)
{
struct udp_pcb *upcb;
err_t err;
/* Create a new UDP control block */
upcb = udp_new(); //创建一个新的UDP控制块
if (upcb)
{
/* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT); //绑定本地IP地址及端口
if(err == ERR_OK)
{
/* Set a receive callback for the upcb */
udp_recv(upcb, udp_echoserver_receive_callback, NULL); //注册接收数据回调函数
}
else
{
udp_remove(upcb);
}
}
}
//服务器端接收数据回调函数
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
/* Tell the client that we have accepted it */
udp_sendto(upcb, p,addr,port); //回显数据
/* Free the p buffer */
pbuf_free(p);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
在main.c文件中,在LWIP初始化之后,增加服务器端初始化函数,即可实现服务器端功能,实现数据回显功能。
udp_echoserver_init();
- 1
2.客户端
//接收数据回调函数声明
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
u8_t data[100]={0x00}; //数据buffer初始化
__IO uint32_t message_count = 0;
struct udp_pcb *upcb; //UDP控制块初始化
//UDP客户端连接函数
void udp_echoclient_connect(void)
{
ip_addr_t DestIPaddr;
err_t err;
/*assign destination IP address */
IP4_ADDR( &DestIPaddr, 192, 168, 1, 103 ); //设置服务器端的IP地址
/* Create a new UDP control block */
upcb = udp_new(); //创建一个新的UDP控制块
if (upcb!=NULL)
{
/* configure destination IP address and port */
err= udp_connect(upcb, &DestIPaddr, 7); //服务器端地址、端口配置
if (err == ERR_OK)
{
printf("local port is %d\r\n",upcb->local_port);
/* Set a receive callback for the upcb */
udp_recv(upcb, udp_receive_callback, NULL); //注册回调函数
udp_echoclient_send(); //**数据发送,第一次连接时客户端发送数据至服务器端,发送函数中会遍历查找源IP地址的配置,如果源IP地址未配置,则数据发送失败。该处出现的问题在后面总结中提到了**
}
}
}
//客户端数据发送函数
void udp_echoclient_send(void)
{
struct pbuf *p;
sprintf((char*)data, "sending udp client message %d", (int)message_count);
/* allocate pbuf from pool*/
p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);
printf("test1\r\n");
if (p != NULL)
{
printf("test2\r\n");
/* copy data to pbuf */
pbuf_take(p, (char*)data, strlen((char*)data));
/* send udp data */
udp_send(upcb, p); //发送数据
/* free pbuf */
pbuf_free(p);
}
printf("test3\r\n");
}
//客户端接收数据回调函数
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
/* send udp data */
udp_send(upcb, p); //数据回显
/* free pbuf */
pbuf_free(p);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
在main.c文件中,在LWIP初始化之后,增加客户端初始化函数,即可实现客户端功能,实现数据回显功能。
udp_echoclient_connect();
- 1
3.总结
- 基于STM32CUBEMX工具的便利性,很方便的图形化配置界面,可以直接生成需要的底层驱动代码,本次工程即直接生成了RMII+LWIP代码,主要工作放置在UDP客户端及服务器端代码的处理上。
- 对于生成过程中,我选择了DHCP服务,即自动获取IP地址。本来该方式是随时根据网络环境动态获取IP地址,是很便利的一种方法。但是对于我这个初学者,在使用UDP客户端时,想在配置完服务器端IP、端口号之后,向服务器端发送数据。参考了许多网上的实例都无法实现,后来使用printf打印,发现在此处send数据时,源IP地址为空,造成数据无法正常发送出去,只能在callback回调函数中进行数据发送。后面暂时去掉了DHCP服务,使用自己配置的IP则无此现象。卡了好久,做个记录。
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
</div>