UDP服务器和客户端在编程上的区别
在上一篇文章中我们讨论了如何基于lwIP的RAW API的方法搭建UDP服务器,这里我们讨论怎么去搭建客户端。
客户端和服务器的主要区别在于:
服务器必须将udp_pcb绑定到一个指定的端口号上,而客户端不用,因为协议栈会自动为客户端分配端口号
客户端必须用udp_connect指定远程服务器的IP地址和端口号,因为一个udp_pcb处于连接状态的前提是必须为udp_pcb指定本地IP+端口号 和远程IP+端口号。
UDP客户端搭建流程
使用 udp_new创建新的udp_pcb
使用udp_connect直接连接远程服务器的IP地址和端口号
构建数据发送函数或者接受回调函数
YuTong Electric
编程前的准备
YuTong Electric
巧妇难为无米之炊,在编码开始之前我们会用到几个API函数,那么首先要搞懂这些API函数是什么意思。
IP4_ADDR
IP4_ADDR可以直接构建一个ip_addr的结构体 比如:
ip_addr_t DestIPaddr;
IP4_ADDR( &DestIPaddr, 192, 168, 1, 103 );
pbuf的释放 -pbuf_free
在udp的接收函数中,一定不要忘记的一件事就是要记得释放pbuf .pbuf 的释放函数是pbuf_free.
pbuf 的分配函数pbuf_alloc的使用
作为客户端也好,服务器也罢,一般情况下我们要和对端进行数据交互,通常会调用pbuf来构造数据结构,而pbuf的分配函数pbuf_alloc的参数需要我们了解。一下是 pbuf_alloc的函数原型
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag)
其中pbuf_layer 是指你用的pbuf运行在那一层,可选项有PBUF_TRANSPORT、PBUF_IP、PBUF_LINK、PBUF_RWA. 我们的应用是位于传输层的UDP协议,所以选择PBUF_TRANSPORT。 其实这几个层的区别就是在于构建的pbuf需要包含对于层的首部字段offset。
pbuf_flag 是指构造数据使用的内存方式是内存堆(PBUF_RAM)还是内存池。一般情况下对于我们的应用程序选择PBUF_RAM
最后要注意的是用完以后要记得释放
程序编码实例
YuTong Electric
//*****************************************************************************
//
// udp_clientc- Driver for the udp client.
//
// Copyright (c) 2017-2023 YuTong Electronic technology All rights reserved.
// Software License Agreement
//
// @File Info ----------------------------------------------- -----------------------------
// Author: YuTong
// Date: 2017/10/26
// Summary: udp client example using lwIP and based on RAW API
//*****************************************************************************
#include "lwi;
#include "lwi;
#include "lwi;
#include "lwi;
#include "lwi;
#include "lwi;
#include "lwi;
#include "lwi;
#include <;
#include <;
#include "ud;
//接收数据回调函数声明
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初始化
uint32_t message_count = 0;
struct udp_pcb *upcb; //UDP控制块初始化
//*****************************************************************************
//
//! Initializes udp client
//!
//*****************************************************************************
void udp_client_init(void)
{
ip_addr_t ServerIpAddr;
err_t err;
/*assign destination IP address */
IP4_ADDR( &ServerIpAddr, 10, 10, 6, 187 ); //设置服务器端的IP地址
/*Create a new UDP control block */
upcb = udp_new();
if (upcb!=NULL)
{
/* configure destination IP address and port */
err= udp_connect(upcb, &ServerIpAddr, 57000);
//服务器端地址、端口配置
if (err == ERR_OK)
{
/* Set a receive callback for the upcb */
udp_recv(upcb, udp_receive_callback, NULL); //注册回调函数
udp_echoclient_send();
}
}
}
//客户端数据发送函数
void udp_echoclient_send(void)
{
struct pbuf *p;
sprintf((char*)data, "sending udp client message %d", (int)message_count);
/* allocate pbuf from ram*/
p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_RAM);
if (p != NULL)
{
/* copy data to pbuf */
pbuf_take(p, (char*)data, strlen((char*)data));
/* send udp data */
udp_send(upcb, p); //发送数据
/* free pbuf */
pbuf_free(p);
}
}
//客户端接收数据回调函数
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);
}