LwIP应用开发笔记之三:LwIP无操作系统UDP客户端
前一节我们实现了基于RAW API的UDP服务器,在接下来,我们进一步利用RAW API实现UDP客户端。
1、UDP协议简述
UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,处于传输层,是IP协议的上层协议。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
UDP报头由4个域组成,其中每个域各占用2个字节,具体如下:源端口号、目标端口号、数据报长度、校验值。其数据结构如下:
UDP协议使用端口号为不同的应用保留其各自的数据传输通道。UDP和TCP协议正是采用这一机制实现对同一时刻内多项应用同时发送和接收数据的支持。数据发送一方(可以是客户端或服务器端)将UDP数据包通过源端口发送出去,而数据接收一方则通过目标端口接收数据。有的网络应用只能使用预先为其预留或注册的静态端口;而另外一些网络应用则可以使用未被注册的动态端口。因为UDP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。一般来说,大于49151的端口号都代表动态端口。
数据报的长度是指包括报头和数据部分在内的总字节数。因为报头的长度是固定的,所以该域主要被用来计算可变长度的数据部分。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报头在内的数据报的最大长度为65535字节。不过,一些实际应用往往会限制数据报的大小,有时会降低到8192字节。
UDP协议使用报头中的校验值来保证数据的安全。校验值首先在数据发送方通过特殊的算法计算得出,在传递到接收方之后,还需要再重新计算。如果某个数据报在传输过程中被第三方篡改或者由于线路噪音等原因受到损坏,发送和接收方的校验计算值将不会相符,由此UDP协议可以检测是否出错。
2、UDP客户端设计
前面我们简要的介绍了UDP协议及其数据报,接下来我们将考虑怎么实现基于UDP协议的客户端。
首先,我们来看一看与UDP相关的API函数,并对它们作一个初步的介绍,应为我们需要使用它们来实现我们的应用。函数及说明如下:
我们已经了解了UDP服务器的实现步骤,接下来我们说明一下UDP客户端的实现步骤。
首先,依然是创建一个新的UDP控制块。
接下来,建立与服务器的连接,配置包括服务器的地址、端口等信息。
接下来,如果连接无问题,则注册客户端回调函数。与服务器端的实现一样,其复杂程度与需要实现的功能相关。我们只是实现一个简单UDP客户端,所以我们向服务器发送固定的信息,收到回复后继续发送对应的信息。
最后,由于客户端是对话的发起方,所以在注册完回调函数后,客户端要发起首次对话。
3、UDP客户端实现
对UDP服务器端的实现,我们依然将器分为两方面内容:一是,UDP客户端的初始化配置部分;二是,UDP客户端的具体实现内容,也就是回调函数的内容。
首先实现UDP客户端的初始化配置部分。定义新的UDP控制块,连接到指定服务器的地址及端口,同样由于我们的验证比较简单我们采用回环服务器端口。然后注册回调函数,发起客户端首次通讯。具体代码如下:
/* UDP客户端初始化配置 */
void UDP_Client_Initialization(void)
{
ip_addr_t DestIPaddr;
err_t err;
struct udp_pcb *upcb;
char data[]="This is a Client."; /* 设置服务器端的IP地址 */
IP4_ADDR( &DestIPaddr,udpServerIP[],udpServerIP[],udpServerIP[],udpServerIP[]); /* 创建一个新的UDP控制块 */
upcb = udp_new(); if (upcb!=NULL)
{
/* 服务器端地址、端口配置 */
err= udp_connect(upcb, &DestIPaddr, UDP_ECHO_SERVER_PORT); if (err == ERR_OK)
{
/* 注册回调函数 */
udp_recv(upcb, UDPClientCallback, NULL);
/**数据发送,第一次连接时客户端发送数据至服务器端,发送函数中会遍历查找源IP地址的配置,如果源IP地址未配置,则数据发送失败。该处出现的问题在后面总结中提到了**/
UdpClientSendPacket(upcb,data);
}
}
}
其次实现UDP客户端的具体实现内容。由于我们实现的简单的响应客户端,所以我们只是给服务器回复相同的内容。
/* 定义UDP客户端数据处理回调函数 */
static void UDPClientCallback(void *arg,struct udp_pcb *upcb,struct pbuf *p,const ip_addr_t *addr,u16_t port)
{
udp_send(upcb, p); //数据回显 pbuf_free(p);
} /* 客户端数据发送函数 */
void UdpClientSendPacket(struct udp_pcb *upcb,char* data)
{
struct pbuf *p; /* 分配内存空间 */
p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL); if (p != NULL)
{ /* 复制数据到pbuf */
pbuf_take(p, (char*)data, strlen((char*)data)); /* 发送数据 */
udp_send(upcb, p); //发送数据 /* 释放pbuf */
pbuf_free(p);
}
}
当然,如果我们不想人云亦云的回复服务器,则可以编辑我们自己的数据包然后发送回去。所以我们想要实现复杂的应用时,只需要重新编写合适的回调函数就可以了!
4、结论
我们完成了简单的,基于RAW API的UDP客户端,其本身并不复杂。同样的我们使用网络软件测试其功能,我们在电脑上建立一个服务器端,然后通过我们这个客户端去连接它。能够进行连接并发送接受数据,说明我们这个客户端的设计是符合要求的。
至此我们完成了UDP客户端及服务器的实现,后续我们将在次基础上实现更为复杂的应用。
欢迎关注:
LwIP应用开发笔记之三:LwIP无操作系统UDP客户端的更多相关文章
- LwIP应用开发笔记之一:LwIP无操作系统基本移植
现在,TCP/IP协议的应用无处不在.随着物联网的火爆,嵌入式领域使用TCP/IP协议进行通讯也越来越广泛.在我们的相关产品中,也都有应用,所以我们结合应用实际对相关应用作相应的总结. 1.技术准备 ...
- LwIP应用开发笔记之四:LwIP无操作系统TFTP服务器
前面我们已经实现了UDP的回环客户端和回环服务器的简单应用,接下来我们实现一个基于UDP的简单文件传输协议TFTP. 1.TFTP协议简介 TFTP是TCP/IP协议族中的一个用来在客户机与服务器之间 ...
- LwIP应用开发笔记之六:LwIP无操作系统TCP客户端
上一篇我们基于LwIP协议栈的RAW API实现了一个TCP服务器的简单应用,接下来一节我们来实现一个TCP客户端的简单应用. 1.TCP简述 TCP(Transmission Control Pro ...
- LwIP应用开发笔记之二:LwIP无操作系统UDP服务器
前面我们已经完成了LwIP协议栈基于逻辑的基本移植,在这一节我们将以RAW API来实现UDP服务器. 1.UDP协议简述 UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包, ...
- LwIP应用开发笔记之七:LwIP无操作系统HTTP服务器
前面我们实现了TCP服务器和客户端的简单应用,接下来我们实现一个基于TCP协议的应用协议,那就是HTTP超文本传输协议 1. HTTP协议简介 超文本传输协议(Hyper Text Transf ...
- LwIP应用开发笔记之八:LwIP无操作系统HTTP客户端
前面我们实现了TCP服务器和客户端的简单应用,接下来我们实现一个基于TCP协议的应用协议,那就是HTTP超文本传输协议 1.HTTP协议简介 超文本传输协议(Hyper Text Transfer P ...
- LwIP应用开发笔记之五:LwIP无操作系统TCP服务器
前面我们实现了UDP服务器及客户端以及基于其上的TFTP应用服务器.接下来我们将实现同样广泛应用的TCP协议各类应用. 1.TCP简述 TCP(Transmission Control Protoco ...
- Kinect开发笔记之三Kinect开发环境配置具体解释
0.前言: 首先说一下我的开发环境,Visual Studio是2013的,系统是win8的64位版本号,SDK是Kinect for windows SDK 1.8版本 ...
- Modbus库开发笔记之三:Modbus TCP Server开发
在完成了前面的工作后,我们就可以实现有针对性的应用了,首先我们来实现Modbus TCP的服务器端应用.当然我们不是做具体的应用,而是对Modbus TCP的服务器端应用进行封装以供有需要时调用. 这 ...
随机推荐
- Codeforces 1187E - Tree Painting(树上所有节点的儿子数量和最大)
乍一看题意比较麻烦,好像要删点求联通性,但其实是相当于求以某一个节点为根时,他的所有后代(儿子,儿子的儿子等等)的儿子的总和最大. 两边dfs即可,第一遍dfs随便找一个点为根,求出每个节点的儿子数s ...
- poj1502 MPI Maelstrom(单源最短路)
题意:表面乍一看output是输出最小值,但仔细研究可以发现,这个最小值是从点1到所有点所花时间的最小值,其实是访问这些节点中的最大值,因为只有访问了最长时间的那个点才算访问了所有点.所以求最短路之后 ...
- 201671010438王奕晗实验十四 团队项目评审&课程学习总结
个人学习总结博客 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 作业学习目标 完成个人软件心得总结 一.结合本学期课程学习内容,对比<实验一 软件工 ...
- 《快活帮》第九次团队作业:【Beta】Scrum meeting 3
项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十三 团队作业9:BETA冲刺与团队项目验收 团队名称 快活帮 作业学习目标 (1)掌 ...
- Spring Boot属性配置文件:application.properties 详解
学习资料 网址 官方说明文档 https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-pro ...
- apollo报:系统出错,请重试或联系系统负责人
说明:基于 docker 搭建的 apollo,创建项目后一直报系统出错,请重试或联系系统负责人错误. 项目人员列表一直空白: 经排查是数据库配置参数不匹配,由于自己的虚拟机 ip 为 192.168 ...
- LeetCode 702. Search in a Sorted Array of Unknown Size
原题链接在这里:https://leetcode.com/problems/search-in-a-sorted-array-of-unknown-size/ 题目: Given an integer ...
- 验证码破解 | Selenium模拟登录简书
使用超级鹰打码平台处理登录的文字点击验证码 import time from io import BytesIO from PIL import Image from selenium import ...
- Numpy | 02 Ndarray 对象
NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引. ndarray 对象是用于存放同类型元素的多维数组. ndarr ...
- Linux防火墙配置方法
1)查看防火墙状态 查看防火墙状态: /etc/init.d/iptables status 暂时关闭防火墙: /etc/init.d/iptables stop 重启防火墙: /etc/init.d ...