物联网协议Coap之Californium CoapServer解析

news2025/1/31 15:49:31

目录

前言

一、CoapServer对象

1、类对象定义

2、ServerInterface接口

3、CoapServer对象

 二、CoapServer服务运行分析

1、CoapServer对象实例化

1.1 调用构造方法

1.2 生成全局配置

1.3 创建Resource对象

1.4-1.8、配置消息传递器、添加CoapResource

1.9-1.12 创建线程池

1.3-1.7 端口绑定、服务配置

2、添加处理器

3、服务启动

 1.1-1.5、绑定端口及相关服务

1.7-1.8 循环启动EndPoint

4、服务运行

总结


前言

        在之前的博客物联网协议之COAP简介及Java实践中,我们采用使用Java开发的Californium框架下进行Coap协议的Server端和Client的协议开发。由于最基础的入门介绍博客,我们没有对它的CoapServer的实现进行深层次的分析。众所周知,Coap和Http协议类似,是分为Server端和Client端的,Server负责接收请求,同时负责业务请求的的处理。而Client负责发起服务,同时接收Server端返回的响应。

        这里将首先介绍CoapServer的内容,本文将采用OOP的设计方法对Californium中Server的实现和启动进行源码级的分析,让读者对Coap的实现有进一步的了解,帮助掌握其设计和实现细节。

一、CoapServer对象

        CoapServer对象是Californium中的核心对象,主要功能作用是创建一个Coap协议的服务端,在指定端口和设置资源处理控制器后,就可以用于接收来自客户端的请求。CoapServer的基本架构如下:


 * +------------------------------------- CoapServer --------------------------------------+
 * |                                                                                       |
 * |                               +-----------------------+                               |
 * |                               |    MessageDeliverer   +--> (Resource Tree)            |
 * |                               +---------A-A-A---------+                               |
 * |                                         | | |                                         |
 * |                                         | | |                                         |
 * |                 .-------->>>------------' | '--------<<<------------.                 |
 * |                /                          |                          \                |
 * |               |                           |                           |               |
 * |             * A                         * A                         * A               |
 * | +-----------------------+   +-----------------------+   +-----------------------+     |
 * | |        Endpoint       |   |        Endpoint       |   |      Endpoint         |     |
 * | +-----------------------+   +-----------------------+   +-----------------------+     |
 * +------------v-A--------------------------v-A-------------------------v-A---------------+
 *              v A                          v A                         v A            
 *              v A                          v A                         v A         
 *           (Network)                    (Network)                   (Network)
 * 

1、类对象定义

        首先我们来看一下CoapServer的类图,从它的类图看一下涉及的类的实现关系。具体如下图所示:

         从上图可以很清晰的看到CoapServer对象的依赖关系,它是ServerInterface的实现类,内部定义了RootResource,它是CoapResource的一个子类。

2、ServerInterface接口

        ServerInterface接口中定义了CoapServer的方法,比如启动、停止、移除、添加服务实例、销毁、addEndpoint等等。来看看其具体的定义:


package org.eclipse.californium.core.server;
import java.net.InetSocketAddress;
import java.util.List;
import org.eclipse.californium.core.network.Endpoint;
import org.eclipse.californium.core.server.resources.Resource;

public interface ServerInterface {
	/**
	 * 启动服务
	 */
	void start();

	/**
	 *停止服务
	 */
	void stop();
	
	/**
	 * 销毁服务
	 */
	void destroy();
	
	/**
	 * 增加资源到服务实例中
	 */
	ServerInterface add(Resource... resources);
	
	/**
	 * 从服务实例中移除资源
	 */
	boolean remove(Resource resource);
	
	void addEndpoint(Endpoint endpoint);

	List<Endpoint> getEndpoints();

	Endpoint getEndpoint(InetSocketAddress address);
	
	Endpoint getEndpoint(int port);
	
}
序号方法说明
1void start();Starts the server by starting all endpoints this server is assigned to Each endpoint binds to its port. If no endpoint is assigned to the  server, the server binds to CoAP's default port 5683.
2void stop();Stops the server, i.e. unbinds it from all ports.
3void destroy();Destroys the server, i.e. unbinds from all ports and frees all system resources.
4ServerInterface add(Resource... resources); Adds one or more resources to the server.
5boolean remove(Resource resource); Adds an endpoint for receive and sending CoAP messages on.
6List<Endpoint> getEndpoints();Gets the endpoints this server is bound to.

3、CoapServer对象

        作为ServerInterface的实现子类,我们来看看Server的具体实现,首先来看下类图:

         成员属性:

序号属性说明
1 Resource rootThe root resource. 
2 NetworkConfig config网络配置对象
3MessageDeliverer delivererThe message deliverer
4List<Endpoint> endpointsThe list of endpoints the server connects to the network.
5ScheduledExecutorService executor;The executor of the server for its endpoints (can be null). 
6boolean runningfalse
7class RootResource extends CoapResource内部实现类

        成员方法除了实现ServerInterface接口的方法之外,还提供以下方法:

序号方法说明
1Resource getRoot()Gets the root of this server
2Resource createRoot()Creates a root for this server. Can be overridden to create another root.

 二、CoapServer服务运行分析

        在了解了上述的CoapServer的相关接口和类的设计和实现后,我们可以来跟踪调试一下CoapServer的实际服务运行过程。它的生命周期运行是一个怎么样的过程,通过下面的章节来进行讲解。

1、CoapServer对象实例化

        在之前的代码中,我们对CoapServer对象进行了创建,来看一下关键代码。从使用者的角度来看,这是最简单不过的一个Java对象实例的创建,并没有稀奇。然而我们要深入到其类的内部实现,明确了解在创建CoapServer的过程中调用了什么逻辑。这里我们将结合时序图的方式进行讲解。


CoapServer server = new CoapServer();// 主机为localhost 端口为默认端口5683

 从上面的时序图可以看到,在CoaServer的内部,在创建其实例的时候。其实做了很多的业务调用,大致可以分为18个步骤,下面结合代码进行介绍:

1.1 调用构造方法

/**
	 * Constructs a server with the specified configuration that listens to the
	 * specified ports after method {@link #start()} is called.
	 *
	 * @param config the configuration, if <code>null</code> the configuration returned by
	 * {@link NetworkConfig#getStandard()} is used.
	 * @param ports the ports to bind to
	 */
	public CoapServer(final NetworkConfig config, final int... ports) {
		
		// global configuration that is passed down (can be observed for changes)
		if (config != null) {
			this.config = config;
		} else {
			this.config = NetworkConfig.getStandard();
		}
		
		// resources
		this.root = createRoot();
		this.deliverer = new ServerMessageDeliverer(root);
		
		CoapResource wellKnown = new CoapResource(".well-known");
		wellKnown.setVisible(false);
		wellKnown.add(new DiscoveryResource(root));
		root.add(wellKnown);
		
		// endpoints
		this.endpoints = new ArrayList<>();
		// sets the central thread pool for the protocol stage over all endpoints
		this.executor = Executors.newScheduledThreadPool(//
				this.config.getInt(NetworkConfig.Keys.PROTOCOL_STAGE_THREAD_COUNT), //
				new NamedThreadFactory("CoapServer#")); //$NON-NLS-1$
		// create endpoint for each port
		for (int port : ports) {
			CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
			builder.setPort(port);
			builder.setNetworkConfig(config);
			addEndpoint(builder.build());
		}
	}

1.2 生成全局配置

        在这里,系统会根据传入的参数进行全局配置,如果不传入config,则自动根据默认参数进行系统配置。否则根据传入参数进行配置。在系统分析时可以看到,如果系统第一次运行,配置文件是不存在的,因此在不存在的时候,会将默认配置写入到工程下面的配置文件中。

public static NetworkConfig getStandard() {
		synchronized (NetworkConfig.class) {
			if (standard == null)
				createStandardWithFile(new File(DEFAULT_FILE_NAME));
		}
		return standard;
	}

public static NetworkConfig createWithFile(final File file, final String header, final NetworkConfigDefaultHandler customHandler) {
		NetworkConfig standard = new NetworkConfig();
		if (customHandler != null) {
			customHandler.applyDefaults(standard);
		}
		if (file.exists()) {
			standard.load(file);
		} else {
			standard.store(file, header);
		}
		return standard;
	}

public void store(File file, String header) {
		if (file == null) {
			throw new NullPointerException("file must not be null");
		} else {
			try (FileWriter writer = new FileWriter(file)) {
				properties.store(writer, header);
			} catch (IOException e) {
				LOGGER.warn("cannot write properties to file {}: {}",
						new Object[] { file.getAbsolutePath(), e.getMessage() });
			}
		}
	}

1.3 创建Resource对象

        通过Server对象本身提供的createRoot()方法进行Resource对象的创建。

1.4-1.8、配置消息传递器、添加CoapResource

CoapResource wellKnown = new CoapResource(".well-known");
wellKnown.setVisible(false);
wellKnown.add(new DiscoveryResource(root));
root.add(wellKnown);
this.endpoints = new ArrayList<>();

1.9-1.12 创建线程池

        这里很重要,通过创建一个容量为16的线程池来进行服务对象的处理。

// sets the central thread pool for the protocol stage over all endpoints
this.executor=Executors.newScheduledThreadPool(this.config.getInt(NetworkConfig.Keys.PROTOCOL_STAGE_THREAD_COUNT), new NamedThreadFactory("CoapServer#")); //$NON-NLS-1$

1.3-1.7 端口绑定、服务配置

        在这里通过for循环的方式,将各个需要处理的端口与应用程序进行深度绑定,配置对应的服务。到此,CoapServer对象已经完成了初始创建。

2、添加处理器

        在创建好了CoapServer对象后,我们使用server.add(new CoapResource())进行服务的绑定,这里的CoapResource其实就是类似于我们常见的Controller类或者servlet。

3、服务启动

下面来看下CoapServer的启动过程,它的启动主要是调用start方法。时序图调用如下图所示:

 1.1-1.5、绑定端口及相关服务

if (endpoints.isEmpty()) {
			// servers should bind to the configured port (while clients should use an ephemeral port through the default endpoint)
			int port = config.getInt(NetworkConfig.Keys.COAP_PORT);
			LOGGER.info("no endpoints have been defined for server, setting up server endpoint on default port {}", port);
			CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
			builder.setPort(port);
			builder.setNetworkConfig(config);
			addEndpoint(builder.build());
		}

1.7-1.8 循环启动EndPoint

int started = 0;
		for (Endpoint ep : endpoints) {
			try {
				ep.start();
				// only reached on success
				++started;
			} catch (IOException e) {
				LOGGER.error("cannot start server endpoint [{}]", ep.getAddress(), e);
			}
		}

每个EndPoint会设置自己的启动方法,

@Override
	public synchronized void start() throws IOException {
		if (started) {
			LOGGER.debug("Endpoint at {} is already started", getUri());
			return;
		}

		if (!this.coapstack.hasDeliverer()) {
			setMessageDeliverer(new ClientMessageDeliverer());
		}
		if (this.executor == null) {
			setExecutor(Executors.newSingleThreadScheduledExecutor(
					new DaemonThreadFactory("CoapEndpoint-" + connector + '#'))); 
			addObserver(new EndpointObserver() {
				@Override
				public void started(final Endpoint endpoint) {
					// do nothing
				}
				@Override
				public void stopped(final Endpoint endpoint) {
					// do nothing
				}
				@Override
				public void destroyed(final Endpoint endpoint) {
					executor.shutdown();
				}
			});
		}

		try {
			started = true;
			matcher.start();
			connector.start();
			for (EndpointObserver obs : observers) {
				obs.started(this);
			}
			startExecutor();
		} catch (IOException e) {
			stop();
			throw e;
		}
	}

4、服务运行

        在经过了上述的实例对象创建、请求资源绑定、服务启动三个环节,一个可用的CoapServer才算是真正完成。运行终端代码可以看到服务已经正常启动。

         由于篇幅有限,类里面还有其他重要的方法不能逐一讲解,感兴趣的各位,可以在工作中认真分析源代码,真正掌握其核心逻辑,做到胸有成竹。

总结

        以上就是本文的主要内容,本文将采用OOP的设计方法对Californium中Server的实现和启动进行源码级的分析,让读者对Coap的实现有进一步的了解,帮助掌握其设计和实现细节。行文仓促,难免有遗漏和不当之处,欢迎各位朋友在评论区批评指正。

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

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

相关文章

C# ASP.NET 实验室 检验中心 医疗LIS源码

LIS系统能够自动处理大量的医学数据&#xff0c;包括样本采集、样本处理、检测分析、报告生成等。它能够快速、准确地进行化验检测&#xff0c;提高医院的运营效率。LIS系统还提供了丰富的数据分析功能&#xff0c;能够对医院化验室的业务流程进行全面、细致的监控。 LIS系统优…

Hooked协议掀起WEB3新浪潮

随着区块链技术和加密货币的兴起&#xff0c;币圈已经成为全球范围内的一个热门领域。在这个充满机遇与挑战的行业中&#xff0c;Hook机制正逐渐成为一种重要的技术手段&#xff0c;为投资者、开发者以及相关机构提供了更多的选择和可能性。本文将详细介绍币圈中的Hook机制&…

Qt/C++音视频开发61-多屏渲染/一个解码渲染到多个窗口/画面实时同步

一、前言 多屏渲染就是一个解码线程对应多个渲染界面&#xff0c;通过addrender这种方式添加多个绘制窗体&#xff0c;我们经常可以在展会或者卖电视机的地方可以看到很多电视播放的同一个画面&#xff0c;原理应该类似&#xff0c;一个地方负责打开解码播放&#xff0c;将画面…

【每日一坑】高Q电感的“SRF”是什么?

先上截图 SRF Self-Resonant Frequency 自我共振频率 电感器中端子电极与绕组导体等之间存在微小的分布容量&#xff0c;因此在特定频率下会发生共振。 此时的频率称为自我共振频率&#xff0c;超过自我共振频率时&#xff0c;电感器将无法发挥其功能。 在为高频电路或高频…

图解集线器、中继器、交换机、网桥、路由器、光猫到底有啥区别?

集线器、中继器、交换机、网桥、光猫这些都是网络设备&#xff0c;但它们在功能、工作层次、数据传输方式、带宽占用方式等方面存在差异 集线器 集线器的英文称为“Hub”。“Hub”是“中心”的意思&#xff08;就像是GitHub&#xff09;&#xff0c;集线器的主要功能是对接收…

张江智荟毁约offer

毕业8年后&#xff0c;找工作被国企歧视学历&#xff01;已经收到了offer&#xff0c;在入职前一周被通知要撤回offer&#xff0c;拒绝录用&#xff0c;理由居然是他们只要本科211以上的人 这是我今天&#xff08;2023-12-26&#xff09;亲身经历的事&#xff0c;听说过面试前…

重磅!最新版北大核心期刊目录出炉,1987种期刊入选!26本期刊已经官宣!

近日&#xff0c;北京大学图书馆网站发布消息&#xff0c;称2023版《中文核心期刊要目总览》已开放采购&#xff0c;这也意味着&#xff0c;备受学界关注的第10版北大核心期刊目录已经出炉。此前&#xff0c;官网已经发布消息称评审工作结束&#xff0c;结果已经通过邮件告知相…

如何将图片(matlab、python)无损放入word论文

许多论文对插图有要求&#xff0c;直接插入png、jpg一般是不行的&#xff0c;这是一篇顶刊文章&#xff08;pdf&#xff09;的插图&#xff0c;放大2400%后依旧清晰&#xff0c;搜罗了网上的方法&#xff0c;总结了一下如何将图片无损放入论文中。 这里主要讨论的是数据生成的图…

数据库(Database)基础知识

什么是数据库 数据库是按照数据结构来组织、存储和管理数据的仓库&#xff0c;用户可以通过数据库管理系统对存储的数据进行增删改查操作。 数据库实际上是一个文件集合&#xff0c;本质就是一个文件系统&#xff0c;以文件的方式&#xff0c;将数据保存在电脑上。 什么是数据…

mvtec3d

以bagel为例&#xff0c;其中有calibration、 bagel # 百吉圈(硬面包)calibrationcamera_parameters.jsontestcombinedgt # 缺陷部位的分割剪影pngrgb # 原图pngxyz # tiffcontamination # 污染物同上crack同上good同上 hole同上 traingoodrgbxyzvalidationgood同traincla…

实现在云服务器ECS实例上绑定和解绑EIP

目录 前言 准备云服务器ECS实例 购买弹性公网IP 绑定公网IP到云服务器 测试通过弹性公网IP访问服务器 绑定EIP到第二台服务器 测试通过弹性公网IP访问服务器 前言 打算在杭州K区和杭州G区部署两台ECS云服务器&#xff0c;然后在其上部署不同的网站页面&#xff0c;购买E…

Java毕业设计—springboot健身房管理系统

一、项目背景介绍&#xff1a; 随着人们生活水平的提高和健康意识的增强&#xff0c;健身行业逐渐兴起并迅速发展。而现代化的健身房管理系统已经成为健身房发展的必备工具之一。传统的健身房管理方式已经无法满足现代化健身房的需求&#xff0c;需要一种更加高效、智能、安全…

C语言——字符函数和字符串函数(三)【strtok,strerror,perror】

&#x1f4dd;前言&#xff1a; 上一篇文章C语言——字符函数和字符串函数&#xff08;二&#xff09;对字符函数和字符串函数strstr&#xff0c;strcmp和strncmp进行了一定的讲解 这篇文章主要讲解以下函数的用法: 1&#xff0c;strtok 2&#xff0c;strerror 3&#xff0c;pe…

线程学习(3)-volatile关键字,wait/notify的使用

​ &#x1f495;"命由我作&#xff0c;福自己求"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;线程学习(2)​​​​ 一.volatile关键字 volatile关键字是多线程编程中一个非常重要的概念&#xff0c;它主要有两个功能&#xff1a;保证内存可见性…

如何配置TLSv1.2版本的ssl

1、tomcat配置TLSv1.2版本的ssl 如下图所示&#xff0c;打开tomcat\conf\server.xml文件&#xff0c;进行如下配置&#xff1a; 注意&#xff1a;需要将申请的tomcat版本的ssl认证文件&#xff0c;如server.jks存放到tomcat\conf\ssl_file\目录下。 <Connector port"1…

MyBatis动态SQL(常用标签)

目录 标签--if 标签--trim 标签--where 标签--set 标签--foreach 和标签--sql和include 根据需求&#xff0c;动态拼接SQL&#xff0c;下面的标签示范使用xml的方式演示。 <if>标签--if 注解&#xff1a; 1.要把全部的SQL放在script标签下 2.使用if标签 可以观…

15-网络安全框架及模型-BLP机密性模型

目录 BLP机密性模型 1 背景概述 2 模型原理 3 主要特性 4 优势和局限性 5 困难和挑战 6 应用场景 7 应用案例 BLP机密性模型 1 背景概述 BLP模型&#xff0c;全称为Bell-LaPadula模型&#xff0c;是在1973年由D.Bell和J.LaPadula在《Mathematical foundations and mod…

PLC-IoT 网关开发札记(1):存档和分发 Android App

开篇记 PLC-IoT 网关是作者开发的产品&#xff0c;根据客户需求&#xff0c;立项开发手机 App&#xff0c;为用户提供一种方便、直观、友好的设备操控方式。网关运行的是嵌入式 Linux 操作系统&#xff0c;计划通过某一种通信协议&#xff08;例如 HTTP&#xff0c;MQTT或者 T…

微信小程序预览pdf,修改pdf文件名

记录微信小程序预览pdf文件&#xff0c;修改pdf名字安卓和ios都可用。 1.安卓和苹果的效果 2.需要用到的api 1.wx.downloadFile wx.downloadFile 下载文件资源到本地。客户端直接发起一个 HTTPS GET 请求&#xff0c;返回文件的本地临时路径 (本地路径)&#xff0c;单次下载…

2024年元旦节放假通知

致尊敬的客户以及全体同仁&#xff1a; 旧岁已展千重锦&#xff0c;新年再进百尺竿。在这辞旧迎新之际&#xff0c;易天光通信提前祝您元旦快乐&#xff01;生意兴隆&#xff0c;身体健康&#xff0c;万事如意&#xff01;根据国家法定假期的规定&#xff0c;并结合公司实际情…