裸写coap客户端首先需要了解coap格式,它和http协议最大的区别是,它是字节协议,每个字节的不同都代表着不同的意义。
小沃通过传送门大致了解了coap的结构,如果大家想深入了解coap协议,请查看传送门。
话不多说,上代码:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
/*
t 0:CON,1:NON,2:ACK,3:RST
method 1:GET,2:POST,3:PUT,4:DELETE
*/
int coaprequest(uint8_t t, uint8_t method,
uint8_t *token, uint8_t tokenlen,
uint8_t *host, uint16_t hostlen,
uint8_t *path, uint16_t pathlen,
uint8_t *body, uint32_t bodylen,
char *buff) { // coap请求
static uint16_t msgid = 0;
int offset = 0;
buff[offset] = 0x40; // ver为01
buff[offset] |= t << 4;
if (tokenlen > 9) {
return 0;
}
buff[offset] |= tokenlen;
offset++;
buff[offset++] = method;
buff[offset++] = msgid >> 8;
buff[offset++] = msgid;
if (tokenlen > 0) {
memcpy(buff+offset, token, tokenlen);
offset += tokenlen;
}
// options
if (hostlen > 0) {
if (hostlen < 13) { // 这里添加一个Uri-Host
buff[offset++] = 0x30 | hostlen;
} else if (hostlen < 269) {
buff[offset++] = 0x3d;
buff[offset++] = hostlen - 13;
} else {
buff[offset++] = 0x3e;
uint16_t tmplen = hostlen - 269;
buff[offset++] = tmplen >> 8;
buff[offset++] = tmplen;
}
memcpy(buff+offset, host, hostlen);
offset += hostlen;
}
if (pathlen > 0) {
if (pathlen < 13) { // 这里再添加一个Uri-Path,说明Uri-Path是13,也就是0x3+0x8,所以用0x80
buff[offset++] = 0x80 | pathlen;
} else if (pathlen < 269) {
buff[offset++] = 0x8d;
buff[offset++] = pathlen - 13;
} else {
buff[offset++] = 0x8e;
uint16_t tmplen = pathlen - 269;
buff[offset++] = tmplen >> 8;
buff[offset++] = tmplen;
}
memcpy(buff+offset, path, pathlen);
offset += pathlen;
}
// body
if (bodylen > 0) {
buff[offset++] = 0xff;
memcpy(buff+offset, body, bodylen);
offset += bodylen;
}
return offset;
}
void main () {
uint8_t buff[32*1024];
char *host = "www.worldflying.cn";
char *path = "/testcoap";
char *body = "{\"temp\":10.00000}";
int len = coaprequest(1, 2, "", 0, host, strlen(host), path, strlen(path), body, strlen(body), buff);
printf("len:%d\n", len);
for (int i = 0 ; i < len ; i++) {
if (i % 16 == 0) {
printf("\n");
}
printf("%02x ", buff[i]);
}
}文章作者:沃航科技