物联网协议Coap之Core和NetWork简介

news2024/9/22 19:24:43

目录

前言

一、Coap的Core包

1、Coap对象

2、Message对象

3、Request对象

4、Response对象

二、Coap的NetWork调试

1、UDP运行模式

 2、Network消息接收

3、Sender线程发送数据 

三、总结


前言

        在之前的博文中,对Californium中Coap的实现进行了简要的介绍,分别从Server和Client两端进行了基础介绍。对于面向连接的连接协议,一定是离不开网络层。本次将重点介绍Coap的Core核心实现以及网络层定义,虽然在Californium协议中,已经全面的实现了Coap协议。

        本文将以Core包和NetWork包为主线,对Coap协议中,关于Californium框架的具体实现方式和代码编写进行讲解,希望对想了解Coap的实现朋友对其有更深入的了解。

一、Coap的Core包

        Coap的核心包定义了Coap适配的协议,请求协议头、响应对象等。主要包含Coap、Message、Option、Request、Response等几个对象。

1、Coap对象

        首先来看一下Coap对象的类图,如下图所示:

         从上图可以看出,Coap类主要是一个常量类,其中包含了消息类型、请求类型编码、响应码、消息格式类型等。请注意这里是采用枚举属性的方式进行定义。比如消息类型的定义,部分代码已精简:

/**
	 * CoAP defines four types of messages:
	 * Confirmable, Non-confirmable, Acknowledgment, Reset.
	 */
	public enum Type {

		/** The Confirmable. */
		CON(0),

		/** The Non-confirmable. */
		NON(1),

		/** The Acknowledgment. */
		ACK(2),

		/** The Reject. */
		RST(3);

		/** The integer value of a message type. */
		public final int value;
	}

以上四种消息类型表示如下:

序号类型说明
1CON需要被确认的请求,如果CON请求被发送,那么对方必须做出响应。这有点像TCP,对方必须给确认收到消息,用以可靠消息传输。
2NON不需要被确认的请求,如果NON请求被发送,那么对方不必做出回应。这适用于消息会重复频繁的发送,丢包不影响正常操作。这个和UDP很像。用以不可靠消息传输。
3ACK 应答消息,对应的是CON消息的应答。
4RST复位消息,可靠传输时候接收的消息不认识或错误时,不能回ACK消息,必须回RST消息。

        请求方法枚举,这里主要定义了Coap请求方法编码,比如GET、POST、PUT等。关键代码如下:

/**
	 * The enumeration of request codes: GET, POST, PUT and DELETE.
	 */
	public enum Code {

		/** The GET code. */
		GET(1),

		/** The POST code. */
		POST(2),

		/** The PUT code. */
		PUT(3),

		/** The DELETE code. */
		DELETE(4);

		/** The code value. */
		public final int value;
	}

2、Message对象

        在通讯建立后,依赖于网络传输对象,Server端和Client端都会进行消息的传递。这是实际数据传递时所依赖的对象。这里重点介绍Message对象,大家可以重点查看Californium的源码来着重了解。首先来看一下Message对象的类图。

         在message对象中,定义了消息类型、mid、token、payload等信息。

消息头(HEAD)

第一行是消息头,必须有,固定4个byte。Ver : 2bit, 版本信息,当前是必须写0x01。T: 2bit, 消息类型,包括 CON, NON. ACK, RST这4种。TKL: 4bit,token长度, 当前支持0~8B长度,其他长度保留将来扩展用。

Code:8bit,分成前3bit(0~7)和后5bit(0~31),前3bit代表类型。 0代表空消息或者请求码, 2开头代表响应码,取值如下:

1 0.00 Indicates an Empty message

2 0.01-0.31 Indicates a request.

3 1.00-1.31 Reserved

4 2.00-5.31 Indicates a response.

5 6.00-7.31 Reserved

Message ID:16bit, 代表消息MID,每个消息都有一个ID ,重发的消息MID不变。token(可选)用于将响应与请求匹配。 token值为0到8字节的序列。 ( 每条消息必须带有一个标记, 即使它的长度为零)。 每个请求都带有一个客户端生成的token, 服务器在任何结果响应中都必须对其进行回应。token类似消息ID,用以标记消息的唯一性。token还是消息安全性的一个设置,使用全8字节的随机数,使伪造的报文无法获得验证通过。

option

请求消息与回应消息都可以0~多个options。 主要用于描述请求或者响应对应的各个属性,类似参数或者特征描述,比如是否用到代理服务器,目的主机的端口等。

payload

实际携带数据内容,若有,前面加payload标识符“0xFF”,如果没有payload标识符,那么就代表这是一个0长度的payload。如果存在payload标识符但其后跟随的是0长度的payload,那么必须当作消息格式错误处理。

/** The Constant NONE in case no MID has been set. */
	public static final int NONE = -1;
	/**
	 * The largest message ID allowed by CoAP.
	 * <p>
	 * The value of this constant is 2^16 - 1.
	 */
	public static final int MAX_MID = (1 << 16) - 1;

	/** The type. One of {CON, NON, ACK or RST}. */
	private CoAP.Type type;

	/** The 16-bit Message Identification. */
	private volatile int mid = NONE; // Message ID

	/**
	 * The token, a 0-8 byte array.
	 * <p>
	 * This field is initialized to {@code null} so that client code can
	 * determine whether the message already has a token assigned or not. An
	 * empty array would not work here because it is already a valid token
	 * according to the CoAP spec.
	 */
	private volatile Token token = null;

	/** The set of options of this message. */
	private OptionSet options;

	/** The payload of this message. */
	private byte[] payload;

	/**
	 * Destination endpoint context. Used for outgoing messages.
	 */
	private volatile EndpointContext destinationContext;

	/**
	 * Source endpoint context. Used for incoming messages.
	 */
	private volatile EndpointContext sourceContext;

	/** Indicates if the message has sent. */
	private volatile boolean sent;

	/** Indicates if the message has been acknowledged. */
	private volatile boolean acknowledged;

	/** Indicates if the message has been rejected. */
	private volatile boolean rejected;

	/** Indicates if the message has been canceled. */
	private volatile boolean canceled;

	/** Indicates if the message has timed out */
	private volatile boolean timedOut; // Important for CONs

	/** Indicates if the message is a duplicate. */
	private volatile boolean duplicate;

	/** Indicates if sending the message caused an error. */
	private volatile Throwable sendError;

	/** The serialized message as byte array. */
	private volatile byte[] bytes;

3、Request对象

        与Http协议类似,Coap中,伴随着每一次的请求发送,势必也会有一个request对象。在request中进行信息的传递。因此,Requet也是继承自Message,其类图如下:

        可以看到,在Reques对象中,针对Get、Put、Post、Delete等不同的方法也进行了定义。

/**
	 * Convenience factory method to construct a POST request and equivalent to
	 * <code>new Request(Code.POST);</code>
	 * 
	 * @return a new POST request
	 */
	public static Request newPost() {
		return new Request(Code.POST);
	}

	/**
	 * Convenience factory method to construct a PUT request and equivalent to
	 * <code>new Request(Code.PUT);</code>
	 * 
	 * @return a new PUT request
	 */
	public static Request newPut() {
		return new Request(Code.PUT);
	}

	/**
	 * Convenience factory method to construct a DELETE request and equivalent
	 * to <code>new Request(Code.DELETE);</code>
	 * 
	 * @return a new DELETE request
	 */
	public static Request newDelete() {
		return new Request(Code.DELETE);
	}

4、Response对象

        response对象与http也是类似的,跟B/S模式是一样的。有Client的请求对象,一定会对应有Server的Response对象。与Request一样,Response也是Message类的子类。

         Reponse的方法相对比较简单,主要是将相应的信息放置到响应对象中,然后返回给前端。其主要的方法如下:

/**
	 * Creates a response to the provided received request with the specified
	 * response code. The destination endpoint context of the response will be
	 * the source endpoint context of the request. Type and MID are usually set
	 * automatically by the {@link ReliabilityLayer}. The token is set
	 * automatically by the {@link Matcher}.
	 *
	 * @param receivedRequest the request
	 * @param code the code
	 * @return the response
	 * @throws IllegalArgumentException if request has no source endpoint
	 *             context.
	 */
	public static Response createResponse(Request receivedRequest, ResponseCode code) {
		if (receivedRequest.getSourceContext() == null) {
			throw new IllegalArgumentException("received request must contain a source context.");
		}
		Response response = new Response(code);
		response.setDestinationContext(receivedRequest.getSourceContext());
		return response;
	}

        由于篇幅有限,关于Core包的相关类介绍先到此,感兴趣的朋友可以下载源码后自己研究,以上将core包中比较重要的四个类进行讲解。下一步在讲解消息构造和方法运行时会更一步的涉及到这些类。因此着重介绍一下,以免不了解的读者不清楚具体的定义。

二、Coap的NetWork调试

        关于Coap的NetWork中的使用,准备结合动态运行过程进行讲解,主要结合Debug的方式,以类图这种分析方法不能完全的展示其调用过程和初始化步骤。比如,为什么说Coap默认是运行在UDP协议之下的,在系统运行时,其协议转换又是怎么工作的。下面将揭开这个面纱。

1、UDP运行模式

        众所周知,Coap默认试运行在UCP协议下的,我们来看一下其具体的定义。在CoapServer中创建CoapEndpoint时,可以看到以下的设置过程。

 在CoapEndpoint.java 中1285行,很清楚的看到这创建了UDPConnector连接器。

 2、Network消息接收

        在进行以上的对象定义之后,Coap基本就可以依赖于网络进行请求的运行了。启动方法

         在这里,分别定义了发送线程集合和接收线程集合,用来保存接收和发送对象。receiverCount默认是16.

3、Sender线程发送数据 

 在这里可以看到要发送的数据包信息,

4、Receiver接收响应

protected void work() throws IOException {
			datagram.setLength(size);
			socket.receive(datagram);
			LOGGER.debug("UDPConnector ({}) received {} bytes from {}:{}",
					new Object[]{socket.getLocalSocketAddress(), datagram.getLength(),
						datagram.getAddress(), datagram.getPort()});
			byte[] bytes = Arrays.copyOfRange(datagram.getData(), datagram.getOffset(), datagram.getLength());
			RawData msg = RawData.inbound(bytes, new AddressEndpointContext(datagram.getAddress(), datagram.getPort()), false);

			receiver.receiveData(msg);
		}

在work方法中进行信息的转换,获取响应报文。通过转换后就可以获取以下报文体:

2.05
{"Content-Format":"text/plain"}
Hello CoAP!This is from Java coap server

Advanced

==[ CoAP Response ]============================================
MID    : 26037
Token  : [6243fee1521b9e40]
Type   : ACK
Status : 2.05
Options: {"Content-Format":"text/plain"}
RTT    : 43333 ms
Payload: 40 Bytes
---------------------------------------------------------------
Hello CoAP!This is from Java coap server
===============================================================

三、总结

        以上就是本文的主要内容,本文将以Core包和NetWork包为主线,对Coap协议中,关于Californium框架的具体实现方式和代码编写进行讲解,希望对想了解Coap的实现朋友对其有更深入的了解。行文仓促,如有不当之处,请留言批评指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1381198.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

31 树的存储结构二

DIsplay() 递归显示 :图示 求树的高度时&#xff0c;递归的技巧 在递归的过程中&#xff1a;ret单独和任意一个子树的子高度比较&#xff0c;如果ret<max&#xff0c;retmax ------------- 注意&#xff1a;组织链表和子链表的【元素类型】都是TLNode* 链表都要先通过TLNod…

Matlab数学建模算法之模拟退火算法(SA)详解

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 &#x1f510;#### 防伪水印——左手の明天 ####&#x1f510; &#x1f497; 大家…

分布式事务:构建无障碍的云原生应用的完美解决方案

目录 一、前言 二、分布式事务概述 2.1 什么是分布式事务 2.2 分布式事务的挑战 2.3 分布式事务的分类 三、传统解决方案分析 3.1 两阶段提交协议&#xff08;2PC&#xff09; 3.2 三阶段提交协议&#xff08;3PC&#xff09; 3.3 补偿事务 3.4 其他传统解决方案 四…

什么是梅尼埃病?

梅尼埃病&#xff08;Meniere’s Disease&#xff0c;MD&#xff09;作为耳鼻咽喉科常见的眩晕疾病&#xff0c;是一种原因不明的、以膜迷路积水为主要病理特征的内耳疾病&#xff0c;临床表现为反复的发作性眩晕、波动性听力下降、耳鸣和耳闷胀感&#xff0c;发病率约为5~20/1…

paypal贝宝怎么绑卡支付

一、PayPal是什么 PayPal是一个很多国家地区通用的支付渠道&#xff0c;我们可以把它理解为一项在线服务&#xff0c;相当于美国版的支付宝。你可以通过PayPal进行汇款和收款&#xff0c;相比传统的电汇和西联那类的汇款方式&#xff0c;PayPal更加简单和容易&#xff0c;被很…

WebRTC入门:基础的核心协议与概念(二十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

如何将.NET 8.0的ASP.NET Core Web API部署成Windows服务

写在前面 前面写了一篇关于将.NET应用转换成Windows服务的方法&#xff0c;其实真正的目的是为了探索如何将Asp.Net Core Web Api 部署成Windows 服务。基于上一篇的基础&#xff0c;只需把创建 WebApplication 的代码放到 BackgroundService 的ExecuteAsync方法中即可。 其中…

redis夯实之路-集群详解

Redis有单机模式和集群模式。 集群是 Redis 提供的分布式数据库方案&#xff0c;集群通过分片( sharding )来实现数据共享&#xff0c;并提供复制和故障转移。集群模式可以有多个 master 。使用集群模式可以进一步提升 Redis 性能&#xff0c;分布式部署实现高可用性&#xff…

快速了解——逻辑回归及模型评估方法

一、逻辑回归 应用场景&#xff1a;解决二分类问题 1、sigmoid函数 1. 公式&#xff1a; 2. 作用&#xff1a;把 (-∞&#xff0c;∞) 映射到 (0&#xff0c; 1) 3. 数学性质&#xff1a;单调递增函数&#xff0c;拐点在x0&#xff0c;y0.5的位置 4. 导函数公式&#xff1a;f…

MySQL 和 Redis 如何保证数据一致性,通过MySQL的binlog实现

1、简介 MySQL 和 Redis 如何保证数据一致性&#xff0c;目前大多讨论的是先更新Redis后更新MySQL&#xff0c;还是先更新MySQL 后更新Redis&#xff0c;这两种方式在实际的应用场景中都不能确保数据的完全一致性&#xff0c;在某些情况下会出现问题&#xff0c;本文介绍使用 C…

Linux Debian12使用VSCode和Python搭建flask开发环境

一、安装VSCode 在Linux Debian12系统上安装VSCode教程可以参考网上相关教程。 二、安装Python 打开VSCode&#xff0c;安装python和python扩展包&#xff0c;如下图所示&#xff1a; 三、创建Python虚拟环境 1.新建文件夹testFlask 2.用vscode打开文件夹testFlask&#xf…

C++/WinRT 简介

C/WinRT 是 Windows 运行时 (WinRT) API 的完全标准新式 C17 语言投影&#xff0c;以基于标头文件的库的形式实现&#xff0c;旨在为你提供对新式 Windows API 的一流访问。 利用 C/WinRT&#xff0c;你可以采用任何符合标准的 C17 编译器创作和使用 Windows 运行时 API。 Wind…

[VSCode] VSCode 常用快捷键

文章目录 VSCode 源代码编辑器VSCode 常用快捷键分类汇总01 编辑02 导航03 调试04 其他05 重构06 测试07 扩展08 选择09 搜索10 书签11 多光标12 代码片段13 其他 VSCode 源代码编辑器 官网&#xff1a;https://code.visualstudio.com/ 下载地址&#xff1a;https://code.visua…

谷歌最新医学领域LLM大模型:AMIE

2024年1月11日Google 研究院发布最新医疗大模型AMIE&#xff1a;用于诊断医学推理和对话的研究人工智能系统。 文章链接&#xff1a;Articulate Medical Intelligence Explorer (AMIE) giuthub&#xff1a;目前代码未开源 关于大模型之前有过一篇总结&#xff1a;大语言模型(L…

C++11 14 17内存管理

智能指针 unique_ptr 初始化 访问和移动赋值 重置和移动内存资源 自定义删除器 shared_ptr 原理 自定义删除器 分配器allocator和new重载 new表达式原理 operator new delete placement new new (buf) 是一种 "placement new" 的使用方式&#xff0c;它允许在已…

Qt QSQlite数据库插入字符串中存在单个双引号或单个单引号解决方案

1. 前言 当进行数据库写入或更新时&#xff0c;有时会遇到存在字符串中包含单个双引号或者单引号。 2. 单引号和双引号""作用 在数据库中&#xff0c;字符串常量时需要用一对英文单引号或英文双引号""将字符串常量括起来。 比如&#xff1a; select * …

vivado 使用源文件

使用源文件 概述 源文件包括从AMD IP添加的设计源、知识产权&#xff08;IP&#xff09;源目录、RTL设计源、从系统添加的数字信号处理&#xff08;DSP&#xff09;源生成器工具和IP子系统&#xff0c;也称为块设计&#xff0c;由IP集成商创建AMD Vivado的功能™ 设计套件。源…

微机原理常考填空总结

hello大家好我是吃个西瓜嘤&#xff0c;这篇节只总结微机原理常考填空题都是干货展示常出现的易错点以及微机原理注意事项。 以下仅代表个人发言 #微机原理 正文开始&#xff1a; 1&#xff0c;区分JZ&#xff0c;JNZ技巧 也就是D70用JZ&#xff1b;D71用JNZ。 JZ;条件ZF1时…

Java SE入门及基础(10)

switch选择结构 1. 概念 switch 表示开关的意思&#xff0c;为了帮助理解&#xff0c;下面以线路为例&#xff0c;进行解释说明 上图中表示一条带有多个开关的线路&#xff0c;当开关打开时&#xff0c;该开关所控制的灯即被点亮。 2. 语法规则 switch ( 表达式 ){ //…

秒懂百科,C++如此简单丨第十二天:ASCLL码

目录 必看信息 Everyday English &#x1f4dd;ASCLL码是什么&#xff1f; &#x1f4dd;ASCLL码表 &#x1f4dd;利用ASCLL码实现大写转小写 &#x1f4dd;小试牛刀 总结 必看信息 ▶本篇文章由爱编程的小芒果原创&#xff0c;未经许可&#xff0c;严禁转载。 ▶本篇文…