Coap协议和Californium框架使用示例
本文主要讲述Coap协议和专门针对Coap协议开发的Californium框架,文章分成3部分,
1. Coap协议介绍
2. Californium框架介绍
3. Californium框架的使用示例,含代码
文章的第一和第二部分在网上有很多文章,内容都差不多,但是关于Californium的使用,网上很少有资料涉及,感兴趣的读者可以重点关注下。进入正题。
一、Coap协议介绍
Coap(Constrained Application Protocol)是一种在物联网世界的类web协议,它的详细规范定义在 RFC 7252。COAP名字翻译来就是“受限应用协议”,顾名思义,使用在资源受限的物联网设备上。物联网设备的ram,rom都通常非常小,运行TCP和HTTP是不可以接受的。
1.1 COAP协议特点
COAP网络传输层采用UDP。
它基于REST,server的资源地址和互联网一样也有类似url的格式,客户端同样有POST,
GET,PUT,DELETE方法来访问server,对HTTP做了简化。
COAP是二进制格式的,HTTP是文本格式的,COAP比HTTP更加紧凑。
轻量化,COAP最小长度仅仅4B。
支持可靠传输,数据重传,块传输。
支持IP多播, 即可以同时向多个设备发送请求。
非长连接通信,适用于低功耗物联网场景。
1.2 COAP协议消息类型
COAP协议有4种消息类型
CON—— 需要被确认的请求,如果CON请求被发送,那么对方必须做出响应。这有点像TCP,对方必须给确认收到消息,用以可靠消息传输。
NON—— 不需要被确认的请求,如果NON请求被发送,那么对方不必做出回应。这适用于消息会重复频繁的发送,丢包不影响正常操作。这个和UDP很像。用以不可靠消息传输。
ACK —— 应答消息,对应的是CON消息的应答。
RST —— 复位消息,可靠传输时候接收的消息不认识或错误时,不能回ACK消息,必须回RST消息。
1.3 COAP消息格式
![](https://img.haomeiwen.com/i24350927/39c46c76f124ddfe.png)
1.3.1 消息头(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字节的随机数,使伪造的报文无法获得验证通过。
1.3.2 option
请求消息与回应消息都可以0~多个options。 主要用于描述请求或者响应对应的各个属性,类似参数或者特征描述,比如是否用到代理服务器,目的主机的端口等。
1.3.3 payload
实际携带数据内容,若有,前面加payload标识符“0xFF”,如果没有payload标识符,那么就代表这是一个0长度的payload。如果存在payload标识符但其后跟随的是0长度的payload,那么必须当作消息格式错误处理。
1.4 COAP的请求码(requests)和响应码(responses)
【0.01】GET方法——用于获得某资源
【0.02】POST方法——用于创建某资源
【0.03】PUT方法——用于更新某资源
【0.04】DELETE方法——用于删除某资源
1.5 CoAP的URL
coap的url和HTTP的有很相似的地方,开头是“coap”对应“http”或者“coaps”对应“https”。
HTTP的默认端口是tcp 80,coap的默认端口是udp 5683(coaps是5684)。
二、Californium框架介绍
Californium框架是一款基于Java实现的Coap技术框架,该项目实现了Coap协议的各种请求响应定义,支持CON/NON不同的可靠性传输模式。Californium 基于分层设计且高度可扩展
Californiium 定义了三层架构
1 网络层,负责处理端口监听,网络数据收发;
2 协议层,负责Coap协议数据包解析及封装,实现消息的路由、可靠性传输、Token处理、观察者模型等等;
3 逻辑层,负责 Resource定义和映射,一个Resource 对应一个URL,可独立实现Coap 请求处理。为了便于理解,可以将resource是为一个servlet或者controller。
对于我们来讲,开发工作主要在逻辑层。
三层架构中都可以支持独立的线程池,其中网络层与协议层的线程池保持独立;
逻辑层可为每个Resource指定独立的线程池,并支持父级继承的机制,即当前Resource若没有定义则沿用父级Resource线程池;
若逻辑层未指定线程池,则默认使用协议层的线程池。
2.1 Californium主要接口介绍
Californium框架的使用并不复杂,我们主要是调用逻辑层的一些类,最常用的一些类和接口如下:
CoapClient:客户端的入口,客户端通过实现CoapClient向服务端发送数据。
CoapServer:服务端的入口,启动服务端,接收客户端传送的数据。
Endpoint:定义为一个端点,通常与一个IP和端口对应,其屏蔽了client和server交互时的网络传输细节。对于client来说,Endpoint代表通讯的服务端地址端口;而对于server来说则代表了绑定监听的地址及端口。CoapEndpoint实现了Endpoint接口。
Exchange:Exchange描述了请求-响应模型,一个Exchange会对应一个Request,相应的Response,以及当前的Endpoint。
CoapResource:最终处理消息的类,通过继承CoapResource类来实现处理客户端发来的请求,通过重写相应的方法处理GET,POST等请求,实现Resource的时候需要指定Resource的名字,这个名字很重要,客户端请求的时候在uri中需要带上Resource的名字,这样框架才会将请求指向对应的Resource。
三、Californium框架的使用示例
示例介绍了一个简单的框架的应用,客户端向服务端发送一段json串,服务端接收并返回接收成功消息。代码基于JDK1.8。
客户端代码:
Client类
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.elements.exception.ConnectorException;
public class Client {
URI uri = null;
CoapClient coapClient = null;
String body = "";
public void init() throws URISyntaxException{
// define the ip and resource name here, ‘test’ is the resource name
uri = new URI("coap://192.168.56.2:5683/test");
coapClient = new CoapClient(uri);
}
// send with post
public void sendPost() throws ConnectorException, IOException {
// the first arg is the request body
// the second arg is the format id of the body, 0-text|50-json
// refer to http://www.iana.org/assignments/core-parameters/core-parameters.xhtml#content-formats to get the format id
CoapResponse response = coapClient.post(this.body.getBytes(), 50);
System.out.println("the respnse code is "+response.getCode());
System.out.println("the respnse body is "+response.getResponseText());
}
public void setBody(String body) {
this.body = body;
}
}
Client 启动类
import java.io.IOException;
import java.net.URISyntaxException;
import org.eclipse.californium.elements.exception.ConnectorException;
import com.ericsson.gpsInterface.test.Client;
import com.sun.org.apache.xml.internal.utils.URI.MalformedURIException;
public class ClientApp {
public static void main(String[] args) throws ConnectorException, IOException, InterruptedException, URISyntaxException {
String body = "{\"id\":\"1\",\"name\":\"tom\"}";
Client myclient = new Client();
myclient.init();
myclient.setBody(body);
System.out.println("message sent");
for(int i=0;i<10;i++) {
myclient.sendPost();
Thread.sleep(100);
}
}
}
服务端代码
Server代码
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import org.eclipse.californium.core.CoapServer;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.core.network.config.NetworkConfig;
public class Server extends CoapServer{
public void myAddEndPoint() throws UnknownHostException {
// get the NetworkConfig object of californium
NetworkConfig config = NetworkConfig.getStandard();
String ip = "0.0.0.0";
InetAddress addr = InetAddress.getByName(ip);
//5683 is the default port
InetSocketAddress bindToAddress = new InetSocketAddress(addr,5683);
// create a new endpoint
CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
builder.setInetSocketAddress(bindToAddress);
builder.setNetworkConfig(config);
// add the endpoint to the server
super.addEndpoint(builder.build());
}
public void start() {
// add the resource to the server, the resource name here is ‘test’ which is corresponding
// to the uri in the client
super.add(new TestResource("test"));
try {
this.myAddEndPoint();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("sever start");
super.start();
}
}
TestResource 代码
import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.coap.CoAP.ResponseCode;
import org.eclipse.californium.core.server.resources.CoapExchange;
public class TestResource extends CoapResource{
public TestResource(String name) {
// define the resource name, also the url path
super(name);
getAttributes().setTitle(name);
}
@Override
public void handleGET(CoapExchange exchange) {
System.out.println("get start");
exchange.respond("got");
}
@Override
public void handlePOST(CoapExchange exchange) {
System.out.println("post start");
String result = exchange.getRequestText();
System.out.println("the received text:"+result);
//exchange.respond(ResponseCode.CHANGED);
exchange.respond(ResponseCode.CHANGED, "good");
}
}
Server启动类代码
public class App{
public static void main( String[] args )
{ Server myserver = new Server();
myserver.start();
}
}
网友评论