libcoap 接口分析与 CoAP 协议开发

article/2025/8/19 10:58:22

libcoap 作为一个重要的 CoAP 开源实现,完整实现了 RFC 7252。很多优秀的 IoT 产品都用到了 libcoap,libcoap 为资源受限的设备(例如计算能力,射频范围,内存,带宽或网络数据包大小)实施轻量级应用程序协议,是一个非常优秀的开源项目。

网络上并没有过多关于使用 libcoap 开发的相关资料,本文以最新版 libcoap 4.2.1 为基础,从 Socket 开始,以最简单的例子(实现起来并不简单)实现一个简单的 server,达到使用 libcoap 进行开发的目的。

准备工作链接
文章项目源码https://github.com/liyansong2018/libcoap-demo
libcoap 库项目地址https://github.com/obgm/libcoap
CoAP 协议分析与测试https://blog.csdn.net/song_lee/article/details/105599391

本文还要求你对 CoAP 协议有一个基本的了解,并且已经安装了 libcoap,详情请访问:CoAP 协议分析与测试,其中也有关于 libcoap 的安装和一些常见问题。

1 libcoap

libcoap 库包含太多的数据类型和 API,这里只分析几个较为重要和常见的,更多文档请参考 libcoap 官方 API 文档 。

1.1 数据类型分析

coap_context_t 结构体存储的是 CoAP 栈的全局状态,可以理解为一个 CoAP 对象,这个对象包括很多 CoAP 属性,是最重要的一个结构体

typedef struct coap_context_t {coap_opt_filter_t known_options;struct coap_resource_t *resources; /**< hash table or list of knownresources */struct coap_resource_t *unknown_resource; /**< can be used for handlingunknown resources */...
}

coap_resource_t 存储 CoAP 资源类型,为了节省空间,采用位域的方式,以位为单位来指定其成员所占内存长度,如下所示,每个成员变量占据一比特,例如,我们可以根据 ->dirty 的值来判断资源是否变化

typedef struct coap_resource_t {unsigned int dirty:1;          /**< set to 1 if resource has changed */unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet*   been notified of the last change */unsigned int observable:1;     /**< can be observed */unsigned int cacheable:1;      /**< can be cached */unsigned int is_unknown:1;     /**< resource created for unknown handler */...
} coap_resource_t;

1.2 API

coap_make_str_const

coap_str_const_t *coap_make_str_const(const char *string);
  • 作用:将 string 类型转换为 coap_str_const_t 类型的常量字符串
  • 返回:指向 coap_str_const_t 类型的指针
  • 入参:字符串(char 类型的指针)

coap_resource_init

coap_resource_t *coap_resource_init(coap_str_const_t *uri_path,int flags);
  • 作用:创建新的资源对象,将 uri 路径初始化为字符串
  • 返回: coap_resource_t 对象
  • 入参:uri_path,新资源的 uri 字符串路径
       flags,内存管理,特别是内存释放

coap_register_handler

void coap_register_handler(coap_resource_t *resource,coap_request_t method,coap_method_handler_t handler);
  • 作用:将指定的资源注册为请求类型的消息处理程序
  • 返回:空
  • 入参:resource 资源
  • method:请求方法
  • handler:要向资源注册的处理程序

coap_add_resource

void coap_add_resource(coap_context_t *context, coap_resource_t *resource);
  • 作用: context 注册给定的资源。资源必须是 coap_resource_init() 或者 coap_resource_unknown_init() 创建。为该资源分配的存储空间由 coap_delete_resource() 释放
    返回:空
  • 入参:context 为 coap 全局状态结构体;resource 是新增的资源类型

coap_add_attr

coap_attr_t *coap_add_attr(coap_resource_t *resource,coap_str_const_t *name,coap_str_const_t *value,int flags);
  • 作用:为给定的资源注册一个属性
  • 返回:指向 coap_attr_t 类型的指针
  • 入参:name 属性名
       value 属性值
       flags 内存管理
  • 备注:flag=COAP_ATTR_FLAGS_RELEASE_NAME 时,coap_add_attr_release() name 会被释放
  • flag= COAP_ATTR_FLAGS_RELEASE_VALUE 时,coap_add_attr_release() value 会被释放

coap_resource_set_get_observable

COAP_STATIC_INLINE void
coap_resource_set_get_observable(coap_resource_t *resource, int mode) {resource->observable = mode ? 1 : 0;
}

作用:将 resource 成员变量 observable 设置为 1 或者 0,也就是 CoAP 的观察模式

2 实际开发

终于到大家比较关心的环节了。libcoap 的使用还是稍稍复杂的,新版本又改了某些 API,使用起来与以前的版本稍稍不同,网上又没有实际案例。开发可参考 libcoap 官方 API 文档 ,但是并不是很全面,有很多用法还是要我们自己不断摸索。

这里,我们举个例子,编写一个 CoAP 服务端,当客户端访问 coap://0.0.0.0/hello,输出 Hello world。虽然案例简单,但是如果使用 libcoap 库实现,还是较为繁琐的。

2.1 创建 Socket

初始化 Socket,这里用到了 coap_address_t 类型,该结构体定义在 address.h 头文件中,从 libcoap 源码中分析

typedef struct coap_address_t {uint16_t port;ip_addr_t addr;
} coap_address_t;

注意其中的 ip_addr_t,这个类型并不 libcoap 源码中定义,也不在标准的 Unix Socket 中,也就是说内核源码中也没有该结构体的声明。笔者后来发现,该结构体是 LwIP 的一个实现

LwIP 是瑞典计算机科学院(SICS)Adam Dunkels 开发的一个小型开源的 TCP/IP 协议栈,相比于计算机中传统的 TCP 协议,可以减少对 RAM 的占用,也就适合使用在物联网设备中了。

LwIP 官方 / github 镜像 项目

http://git.savannah.gnu.org/cgit/lwip.git
https://github.com/lwip-tcpip/lwip.git

在编译 libcoap 源码的过程中,会自动下载该项目,因此这里不必考虑单独克隆 LwIP,下面是可能用到的一些 LwIP 头文件

/** 255.255.255.255 */
#define INADDR_NONE         IPADDR_NONE
/** 127.0.0.1 */
#define INADDR_LOOPBACK     IPADDR_LOOPBACK
/** 0.0.0.0 */
#define INADDR_ANY          IPADDR_ANY
/** 255.255.255.255 */
#define INADDR_BROADCAST    IPADDR_BROADCAST

代码

coap_address_t  serv_addr;
coap_address_init(&serv_addr);
//serv_addr.port 				   = 5683;
serv_addr.addr.sin.sin_family      = AF_INET;
serv_addr.addr.sin.sin_addr.s_addr = INADDR_NONE;
serv_addr.addr.sin.sin_port        = htons(5683); //default port
ctx                                = coap_new_context(&serv_addr);

coap_address_init 初始化 coap_address_t 对象,分配堆空间,存放 serv_addr 指向的结构体。这里 coap_new_context 用来创建 coap_context_t 对象。INADDR_NONE 是 LwIP 中的一个宏,(0.0.0.0),这里是要结合源码来看,才能写出更好的代码。

2.2 初始化资源

static void
hello_handler(coap_context_t *ctx, struct coap_resource_t *resource, coap_session_t *session, coap_pdu_t *request, coap_binary_t *token, coap_string_t *query, coap_pdu_t *response) 
{unsigned char buf[3];const char* response_data     = "Hello World!";response->code           = COAP_RESPONSE_CODE(205);coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);coap_add_data  (response, strlen(response_data), (unsigned char *)response_data);
}hello_resource = coap_resource_init(coap_make_str_const("hello"), 0);
coap_register_handler(hello_resource, COAP_REQUEST_GET, hello_handler);
coap_add_resource(ctx, hello_resource);

coap_resource_init 用于给资源提供路径,路径名为 hello,即该资源的路径为:coap://0.0.0.0/hello。coap_register_handler 将该资源与特定的请求方法,返回的处理方式绑定,决定了该资源,客户端应该使用 GET 方式获取。服务端正确的响应,交给 hello_handler 处理,该函数就是最终的 CoAP 报文处理函数

2.3 监听端口,等待连接

方法一

unsigned wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;while (1)
{int result = coap_run_once(ctx, wait_ms);if (result < 0){break;}//coap_read(ctx, now);
}
coap_free_context(ctx); 

coap_run_once 函数会在 wait_ms 时间内,等待一个新的数据包,ctx 发生变化时,返回状态。整个 while 循环用来监听连接。

方法二:Select

select 是 Linux 系统调用,fd_set 是文件描述符集。select 函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供 select函数来实现多路复用输入/输出模型。

int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);

对 于fd_set 类型通过下面四个宏来操作:

  • FD_ZERO(fd_set *fdset) 将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
  • FD_SET(fd_set *fdset) 用于在文件描述符集合中增加一个新的文件描述符。
  • FD_CLR(fd_set *fdset) 用于在文件描述符集合中删除一个文件描述符。
  • FD_ISSET(int fd,fd_set *fdset) 用于测试指定的文件描述符是否在该集合中。
while (1)
{FD_ZERO(&readfds);FD_SET(coap_fd, &readfds);int result = select( FD_SETSIZE, &readfds, 0, 0, NULL );if (result < 0){exit(1);}else if (result > 0 && FD_ISSET(coap_fd, &readfds)){coap_run_once(ctx, COAP_RUN_NONBLOCK);}}

这里的 coap_run_once 参数 wait_ms 有以下两个值

  • COAP_RUN_NONBLOCK(1) 如果没有更多输入数据包,则无需等待;
  • COAP_RUN_BLOCK(0)会一直等待一个新的数据包进入

2.4 编译和运行

make server
./server

运行结果
在这里插入图片描述

3 总结

libcoap 是一个优秀的 CoAP 协议开源项目,但是使用起来较为复杂,本文在这里只是介绍一些常用结构体和 API 的使用,笔者也不是专门的开发人员,只是为了更好的理解 CoAP 协议的实现,才去使用 libcoap。如果你要实现一个功能性的 CoAP server,一定要结合源码,在理解源码的基础上,才能更好的编写相关代码。


http://chatgpt.dhexx.cn/article/9HBWT7MW.shtml

相关文章

CoAP协议接入

CoAP协议规范 本小节介绍物联网平台支持的CoAP协议规范。 协议版本 支持RFC 7252 Constrained Application Protocol协议&#xff0c;更多信息&#xff0c;请参见RFC 7252。 通道安全 使用DTLS v1.2保证通道安全&#xff0c;更多信息&#xff0c;请参见DTLS v1.2。 开源客…

干货 | CoAP协议例析

点击上方“中兴开发者社区”&#xff0c;关注我们 每天读一篇一线开发者原创好文 在物联网领域中&#xff0c;MQTT和CoAP是最主要的两个应用协议。MQTT&#xff08;Message Queuing Telemetry Transport/消息队列遥测传输&#xff09;是基于TCP的发布/订阅方式的应用协议&#…

CoAP协议简介

学习CoAP最简单的方法便是阅读协议文档。该协议文档并不是那么复杂。当然如果有一个CoAP的简单介绍那就再好不过了。 什么是CoAP CoAP是受限制的应用协议(Constrained Application Protocol)的代名词。在最近几年的时间中&#xff0c;专家们预测会有更多的设备相互连接&#xf…

CoAP 协议学习

CoAP 协议学习 2014年左右智能家居异常火热&#xff0c;由于高效的端到端订阅推送特性&#xff0c;使得MQTT成为了智能家居的首选协议。因此目前各大云平台中&#xff0c;MQTT基本成了标配。 物联网另一个应用协议 CoAP 协议则相对低调&#xff0c;不过由于 NB-IoT 的推出&am…

CoAP协议学习笔记——CoAP格式详解

CoAP是受限制的应用协议(Constrained Application Protocol)的代名词。在当前由PC机组成的世界&#xff0c;信息交换是通过TCP和应用层协议HTTP实现的。但是对于小型设备而言&#xff0c;实现TCP和HTTP协议显然是一个过分的要求。为了让小设备可以接入互联网&#xff0c;CoAP协…

COAP学习笔记

文章目录 一、UDP协议简介二、COAP协议2.1 COAP简介2.2 CoAP消息报文结构i CoAP消息结构 - 消息类型 详解ii CoAP消息结构 - Requset/Response Code 详解iii CoAP消息结构 - Option 详解 2.3 CoAP观察模式2.4 COAP的安全性 三、根据阿里云COAP规范,分析并构建十六进制的报文3.1…

CoAP

CoAP是受限的应用协议(Contrained Application Protocol)的代名词. CoAP是一种应用层协议, 它运行于UDP协议之上. 参考: https://blog.csdn.net/xukai871105/article/details/45167069 CoAP协议综述 和其他TCP IP协议簇中的协议一样, CoAP协议总是以"头"的形式出现…

COAP详解

COAP协议学习 1分析工具 网络包分析利器&#xff1a;wiresharkCOAP协议客户端、服务端&#xff1a;wakaama 源码地址辅助编译工具cmake3&#xff1a;由于wakaama对cmake有版本要求 源码地址 ** 文章后附上wakaama、cmake3编译、使用方法及安装步骤等 2COAP协议介绍 Coap&am…

CoAP协议及开源实现

1. CoAP协议的简单介绍 CoAP是一种面向网络的协议&#xff0c;采用了与HTTP类似的特征&#xff0c;核心内容为资源抽象、REST式交互以及可扩展的头选项等。这些关键特征使得因特网由简单的文档检索机制(World Wide Web)演进成为现在繁荣的应用平台(Web 2.0)。HTTP作为IETF 成功…

CoAP学习笔记——CoAP格式详解

0 前言 CoAP是受限制的应用协议(Constrained Application Protocol)的代名词。在当前由PC机组成的世界&#xff0c;信息交换是通过TCP和应用层协议HTTP实现的。但是对于小型设备而言&#xff0c;实现TCP和HTTP协议显然是一个过分的要求。为了让小设备可以接入互联网&#xff0c…

CoAP协议学习——CoAP基础

【 原连接地址】 更多CoAP文章请参考博文索引——【 物联网学习笔记——索引博文】 推广 《IoT开发实战:CoAP卷》已经由机械工业出版社出版&#xff0c;如果想学习CoAP的更多内容请于淘宝、天猫或京东平台搜索"CoAP"。 什么是CoAP CoAP是受限制的应用协议(Constraine…

COAP介绍

什么是COAP CoAP是受限制的应用协议(Constrained Application Protocol)的代名词。在最近几年的时间中&#xff0c;专家们预测会有更多的设备相互连接&#xff0c;而这些设备的数量将远超人类的数量。在这种大背景下&#xff0c;物联网和M2M技术应运而生。虽然对人而言&#xf…

时序数据库InfluxDB和关系型数据库MySQL的区别及适用场景

数据库主要分为关系型数据库和非关系型数据库&#xff0c;大家所熟悉的数据库中&#xff0c;属Oracle、MySQL和Microsoft SQL Server最出名&#xff0c;使用人数最多&#xff0c;这三种都属于关系型数据库&#xff0c;之所以使用人数这么多&#xff0c;是因为关系型数据库符合大…

vm时序数据库-导入数据

时间序列数据可以通过任何支持的摄取协议导入&#xff1a; Prometheus remote_write API. See these docs for details.DataDog submit metrics API. See these docs for details.InfluxDB line protocol. See these docs for details.Graphite plaintext protocol. See these …

三种常用时序数据库对比调研-InfluxDB、Prometheus、IotDB

1、引言 时序数据治理是数据治理领域核心、打通IT与OT域数据链路&#xff0c;是工业物联网基石、大数据价值创造的关键、企业管理提升的发动机、是数字化转型的重要支撑。 工业企业在生产经营过程中&#xff0c;会运用物联网技术&#xff0c;采集大量的数据并进行实时处理&am…

时序数据 mysql存储_【时序数据库】时序数据库介绍

1.基本概念 时序数据库(Time Series Database)是用于存储和管理时间序列数据的专业化数据库。时序数据库特别适用于物联网设备监控和互联网业务监控场景。 下面介绍下时序数据库的一些基本概念(不同的时序数据库称呼略有不同)。 1.1 度量(metric) 监测数据的指标,例如风力和温…

mysql 时序数据库_时序数据库介绍和使用(转)

1.基础 1.1 时序数据的定义 什么是时间序列数据(Time Series Data,TSD,以下简称时序)从定义上来说,就是一串按时间维度索引的数据。用描述性的语言来解释什么是时序数据,简单的说,就是这类数据描述了某个被测量的主体在一个时间范围内的每个时间点上的测量值。它普遍存在于…

关于时序数据库

https://blog.csdn.net/ransom0512/article/details/78114167 看了一些时序数据库&#xff0c;没有太深入&#xff0c;有一些大概认识&#xff0c;记录下来。 1. 核心 数据存储分为行存储或者列存储&#xff0c;由于列存储的高压缩比&#xff0c;现在使用列存储的比较多一…

时序数据库Machbase

Background 最近偶然接触到Machbase&#xff0c;发现相关信息很少&#xff0c;于是自己做了一些简单的了解&#xff0c;这里记录下&#xff0c;方便有兴趣的童靴参考哈。 1、官方介绍 Machbase是韩国的一家公司开发的一款类似InfluxDB、DolphinDB、TDengine等时序数据库产品&am…

用友:时序数据库要更懂业务场景

本文来自IT168 作者卢敏 时序数据库是针对时间戳或时间序列数据优化的数据库。比如工业企业为了管好工业设备&#xff0c;需要用传感器收集一些带有时间标签的数据&#xff0c;这些数据既要求“超大规模数据瞬时写入”&#xff0c;又要求实现乱序管理。 用友网络助理总裁何冠…