golang实现CoAP协议客户端与服务端通信的插件库canopus的使用
Golang实现CoAP协议客户端与服务端通信的插件库Canopus的使用
Canopus是一个实现了RFC7252约束应用协议(CoAP)的客户端/服务器库。
简单示例
服务端代码
// 创建CoAP服务器
server := canopus.NewServer()
// 注册GET请求处理函数
server.Get("/hello", func(req canopus.Request) canopus.Response {
// 创建确认消息
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Acknowledged: " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
// 监听5683端口
server.ListenAndServe(":5683")
客户端代码
// 连接到服务器
conn, err := canopus.Dial("localhost:5683")
if err != nil {
panic(err.Error())
}
// 创建GET请求
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID()).(*canopus.CoapRequest)
req.SetStringPayload("Hello, canopus")
req.SetRequestURI("/hello")
// 发送请求
resp, err := conn.Send(req)
if err != nil {
panic(err.Error())
}
// 打印响应
fmt.Println("Got Response:" + resp.GetMessage().GetPayload().String())
观察/通知模式示例
服务端代码
server := canopus.NewServer()
server.Get("/watch/this", func(req canopus.Request) canopus.Response {
msg := canopus.NewMessageOfType(canopus.MessageAcknowledgment, req.GetMessage().GetMessageId(), canopus.NewPlainTextPayload("Acknowledged"))
res := canopus.NewResponse(msg, nil)
return res
})
// 每3秒发送一次通知
ticker := time.NewTicker(3 * time.Second)
go func() {
for {
select {
case <-ticker.C:
changeVal := strconv.Itoa(rand.Int())
fmt.Println("[SERVER << ] Change of value -->", changeVal)
server.NotifyChange("/watch/this", changeVal, false)
}
}
}()
// 观察请求回调
server.OnObserve(func(resource string, msg canopus.Message) {
fmt.Println("[SERVER << ] Observe Requested for " + resource)
})
server.ListenAndServe(":5683")
客户端代码
conn, err := canopus.Dial("localhost:5683")
// 观察资源
tok, err := conn.ObserveResource("/watch/this")
if err != nil {
panic(err.Error())
}
// 创建观察通道
obsChannel := make(chan canopus.ObserveMessage)
done := make(chan bool)
go conn.Observe(obsChannel)
// 处理通知
notifyCount := 0
for {
select {
case obsMsg, _ := <-obsChannel:
if notifyCount == 5 {
fmt.Println("[CLIENT >> ] Canceling observe after 5 notifications..")
go conn.CancelObserveResource("watch/this", tok)
go conn.StopObserve(obsChannel)
return
} else {
notifyCount++
resource := obsMsg.GetResource()
val := obsMsg.GetValue()
fmt.Println("[CLIENT >> ] Got Change Notification for resource and value: ", notifyCount, resource, val)
}
}
}
使用PSK的dTLS示例
服务端代码
server := canopus.NewServer()
server.Get("/hello", func(req canopus.Request) canopus.Response {
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Acknowledged: " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
// 设置PSK处理函数
server.HandlePSK(func(id string) []byte {
return []byte("secretPSK")
})
// 监听DTLS端口
server.ListenAndServeDTLS(":5684")
客户端代码
// 使用DTLS连接
conn, err := canopus.DialDTLS("localhost:5684", "canopus", "secretPSK")
if err != nil {
panic(err.Error())
}
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID())
req.SetStringPayload("Hello, canopus")
req.SetRequestURI("/hello")
resp, err := conn.Send(req)
if err != nil {
panic(err.Error())
}
fmt.Println("Got Response:" + resp.GetMessage().GetPayload().String())
CoAP-CoAP代理示例
后端服务端代码
server := canopus.NewServer()
server.Get("/proxycall", func(req canopus.Request) canopus.Response {
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Data from :5685 -- " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
server.ListenAndServe(":5685")
代理服务端代码
server := canopus.NewServer()
// 启用CoAP代理
server.ProxyOverCoap(true)
server.Get("/proxycall", func(req canopus.Request) canopus.Response {
canopus.PrintMessage(req.GetMessage())
msg := canopus.ContentMessage(req.GetMessage().GetMessageId(), canopus.MessageAcknowledgment)
msg.SetStringPayload("Acknowledged: " + req.GetMessage().GetPayload().String())
res := canopus.NewResponse(msg, nil)
return res
})
server.ListenAndServe(":5683")
客户端代码
conn, err := canopus.Dial("localhost:5683")
if err != nil {
panic(err.Error())
}
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID())
// 设置代理URI
req.SetProxyURI("coap://localhost:5685/proxycall")
resp, err := conn.Send(req)
if err != nil {
println("err", err)
}
canopus.PrintMessage(resp.GetMessage())
CoAP-HTTP代理示例
代理服务端代码
server := canopus.NewServer()
// 启用HTTP代理
server.ProxyOverHttp(true)
server.ListenAndServe(":5683")
客户端代码
conn, err := canopus.Dial("localhost:5683")
if err != nil {
panic(err.Error())
}
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get, canopus.GenerateMessageID())
// 设置HTTP代理URI
req.SetProxyURI("https://httpbin.org/get")
resp, err := conn.Send(req)
if err != nil {
println("err", err)
}
canopus.PrintMessage(resp.GetMessage())
更多关于golang实现CoAP协议客户端与服务端通信的插件库canopus的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现CoAP协议客户端与服务端通信的插件库canopus的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用Canopus库实现CoAP协议通信
Canopus是一个轻量级的Go语言CoAP协议实现库,支持客户端和服务端功能。下面我将介绍如何使用Canopus实现基本的CoAP通信。
安装Canopus
首先需要安装Canopus库:
go get github.com/zubairhamed/canopus
CoAP服务端实现
package main
import (
"fmt"
"log"
"time"
"github.com/zubairhamed/canopus"
)
func main() {
// 创建CoAP服务端
server := canopus.NewServer()
// 设置默认路由,处理所有请求
server.GetDefaultHandleFunc(func(req canopus.CoapRequest) canopus.CoapResponse {
// 打印接收到的请求信息
fmt.Printf("Received request: %+v\n", req.GetMessage())
// 创建响应消息
res := canopus.NewResponse(canopus.NewEmptyMessage(req.GetMessage().MessageId), nil)
res.SetCode(canopus.Content)
res.SetPayload(canopus.NewPlainTextPayload("Hello from CoAP Server!"))
return res
})
// 添加特定资源路由
server.Get("/time", func(req canopus.CoapRequest) canopus.CoapResponse {
res := canopus.NewResponse(canopus.NewEmptyMessage(req.GetMessage().MessageId), nil)
res.SetCode(canopus.Content)
res.SetPayload(canopus.NewPlainTextPayload(time.Now().Format(time.RFC3339)))
return res
})
// 启动服务端,监听5683端口(CoAP默认端口)
err := server.ListenAndServe(":5683")
if err != nil {
log.Fatal(err)
}
}
CoAP客户端实现
package main
import (
"fmt"
"log"
"github.com/zubairhamed/canopus"
)
func main() {
// 创建CoAP客户端
client := canopus.NewClient()
// 连接到服务端
conn, err := client.Dial("localhost:5683")
if err != nil {
log.Fatal(err)
}
// 发送GET请求到默认资源
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get)
req.SetRequestURI("/")
resp, err := conn.Send(req)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Response from server: %s\n", resp.GetMessage().Payload.String())
// 发送GET请求到/time资源
req = canopus.NewRequest(canopus.MessageConfirmable, canopus.Get)
req.SetRequestURI("/time")
resp, err = conn.Send(req)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Current time from server: %s\n", resp.GetMessage().Payload.String())
}
高级功能
观察资源(Observe)
Canopus支持CoAP的观察功能,可以订阅资源的变化:
// 服务端代码 - 添加可观察资源
server.Get("/temp", func(req canopus.CoapRequest) canopus.CoapResponse {
res := canopus.NewResponse(canopus.NewEmptyMessage(req.GetMessage().MessageId), nil)
res.SetCode(canopus.Content)
res.SetPayload(canopus.NewPlainTextPayload(fmt.Sprintf("%.1f°C", getTemperature())))
// 标记为可观察资源
res.SetObserve(1)
return res
})
// 客户端代码 - 观察资源
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get)
req.SetRequestURI("/temp")
req.SetObserve(0) // 启用观察
// 设置观察回调
conn.Observe(req, func(resp canopus.CoapResponse) {
fmt.Printf("Temperature update: %s\n", resp.GetMessage().Payload.String())
})
资源发现
Canopus支持CoAP的资源发现功能:
// 客户端发现服务端资源
req := canopus.NewRequest(canopus.MessageConfirmable, canopus.Get)
req.SetRequestURI("/.well-known/core")
resp, err := conn.Send(req)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Discovered resources: %s\n", resp.GetMessage().Payload.String())
块传输(Block-wise Transfer)
对于大文件传输,Canopus支持块传输:
// 服务端代码 - 处理块传输
server.Get("/large", func(req canopus.CoapRequest) canopus.CoapResponse {
largeData := make([]byte, 2048) // 2KB数据
// 填充数据...
res := canopus.NewResponse(canopus.NewEmptyMessage(req.GetMessage().MessageId), nil)
res.SetCode(canopus.Content)
res.SetPayload(canopus.NewBytesPayload(largeData))
// 启用块传输
res.SetBlock2(canopus.Block2{
Num: 0,
More: true,
Size: 64, // 块大小
})
return res
})
注意事项
- Canopus默认使用UDP协议,CoAP也可以运行在TCP上(CoAP over TCP)
- 生产环境中应考虑添加安全层(CoAPs/DTLS)
- 对于资源受限设备,可以调整消息大小和重传参数
- Canopus还支持CoAP代理功能,可以构建CoAP-HTTP网关
Canopus提供了完整的CoAP协议实现,包括消息类型、选项和扩展功能,适合构建物联网设备和服务器之间的轻量级通信。