在 libcoap coap 服务器 GET 响应处理程序中如何访问对 URI 的查询添加?
In libcoap coap server GET response handler how to access query additions to URI?
我正在使用 Raspbian 下的 libcoap-dev-1
库和 Raspberry Pi 使用带有简单客户端和简单服务器的库来实现 CoAP 协议。我有一个工作的客户端和一个工作的服务器,现在正在尝试修改服务器,以便它可以接受带有查询字符串的 URI,然后我可以获取 URI 的查询字符串。
我目前正在测试的URI是coap://127.0.0.1/hello?item=1
,它有一个查询参数,?
之后的item=1
。
服务器中的请求处理程序是以下函数,它是一个存根,用于测试将固定响应作为 JSON 文本发送回客户端。这工作正常,客户端收到 JSON 文本并能够使用 Fast JSON 库来解析它。
// header for the libcoap library. it should be in /usr/include/coap
#include <coap/coap.h>
/*
* The resource handler which the libcoap library will invoke when the registered
* URI is specified.
*/
static void
hello_handler(coap_context_t *ctx, struct coap_resource_t *resource,
const coap_endpoint_t *local_interface, coap_address_t *peer,
coap_pdu_t *request, str *token, coap_pdu_t *response)
{
static int iCount = 0;
unsigned char buf[3];
const char* response_data = "{\"device\": \"DEV-01-123\", \"item\" : %d }";
char response_buf[256] = {0};
response->hdr->code = COAP_RESPONSE_CODE(205);
coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
sprintf (response_buf, response_data, iCount);
coap_add_data (response, strlen(response_buf), (unsigned char *)response_buf);
iCount++;
printf (" request %s\n", resource->uri.s);
}
函数末尾的printf()
打印不带查询部分的URI。所以打印的是 hello
而不是 hello?item=1
.
我的问题是如何访问客户端发送的 URI 的查询部分?
用于创建服务器和客户端的 libcoap
函数需要更多步骤作为格式化和检索 URI 和 URI 查询信息的一部分 into/from CoAP 请求。
完整的示例应用程序 client.c 和 server.c 在我的 GitHub 存储库中 https://github.com/RichardChambers/raspberrypi/tree/master/coap。
在服务器端,消息处理程序将使用一个选项迭代器,一个 coap_opt_iterator_t
结构对象,来迭代 coap_pdu_t
结构请求对象的选项。迭代时,服务器将寻找 COAP_OPTION_URI_QUERY
类型的选项,其中包含查询参数,通常是关键字等值对。
所以发布问题的函数 hello_handler()
可以用辅助函数重写,以获取 URI 查询项列表,如下所示:
/*
* The following helper function, printQueryOption(), is used to
* iterate over the list of options looking for query type options
* to the base URI. This is analogous to a web URL that contains
* a question mark followed by options such as:
* http://www.server.com/hello?type=1,id=2345
*
* We will return a value of 1 (true) if we found something or a value
* of 0 (false) if we do not.
*/
static int
printQueryOption (coap_pdu_t *request, coap_opt_iterator_t * popt_iter )
{
int iRet = 0;
coap_opt_t *option;
// iterate over the options looking for queries. If we find one
// then print it and return a value of 1, true, to indicate we
// found one. If we don't find any then return the default value
// of 0, false.
while (option = coap_option_next(popt_iter)) {
// found an option, is it a query option or not.
if (popt_iter->type != COAP_OPTION_URI_QUERY) continue;
// it is a query option so print out the query text.
char xBuff[128] = {0};
strncpy (xBuff, COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option));
printf (" option len %d\n %s \n", COAP_OPT_LENGTH(option), xBuff);
// indicate that we found a query option.
iRet = 1;
break;
}
return iRet;
}
/*
* The resource handler which the libcoap library will invoke when the registered
* URI is specified. This is a simple request handler which will just display some
* of the information from the request.
*/
static void
hello_handler(coap_context_t *ctx, struct coap_resource_t *resource,
const coap_endpoint_t *local_interface, coap_address_t *peer,
coap_pdu_t *request, str *token, coap_pdu_t *response)
{
static int iCount = 0; // a simple count to provide some kind of response data.
unsigned char buf[3];
const char* response_data = "{\"device\": \"DEV-01-123\", \"item\" : %d }";
char response_buf[256] = {0};
// generate a response to this request. we have a hard coded JSON text that
// we are using as a stub for testing.
response->hdr->code = COAP_RESPONSE_CODE(205);
coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
sprintf (response_buf, response_data, iCount);
coap_add_data (response, strlen(response_buf), (unsigned char *)response_buf);
iCount++; // this count is some type of varying data so that we can see things are working.
if (request != NULL) {
// there is a request URI so lets print out the base URI and then
// iterate over the options looking for the Query type options.
coap_opt_iterator_t opt_iter;
printf (" request %s\n", resource->uri.s);
coap_option_iterator_init (request, &opt_iter, COAP_OPT_ALL);
// iterate over the options of the request printing out any
// query text that may exist.
while (printQueryOption (request, &opt_iter));
} else {
printf (" request - NONE\n");
}
}
在客户端,我们将构建我们的请求,添加我们想要包含在请求中的查询,并调用一系列函数 coap_add_option()
,如:
coap_split_uri(server_uri, strlen(server_uri), &uri);
request = coap_new_pdu();
request->hdr->type = COAP_MESSAGE_CON;
request->hdr->id = coap_new_message_id(ctx);
request->hdr->code = get_method;
printf (" Request URI: path %d %s\n", uri.path.length, uri.path.s);
coap_add_option(request, COAP_OPTION_URI_PATH, uri.path.length, uri.path.s);
sprintf (server_query, "item=%d", iItem);
coap_add_option(request, COAP_OPTION_URI_QUERY, strlen(server_query), server_query);
printf (" Query: len %d %s\n", strlen(server_query), server_query);
sprintf (server_query, "device=%s", aszDevName);
coap_add_option(request, COAP_OPTION_URI_QUERY, strlen(server_query), server_query);
printf (" Query: len %d %s\n", strlen(server_query), server_query);
sprintf (server_query, "tempo=%s", aszTempoName);
coap_add_option(request, COAP_OPTION_URI_QUERY, strlen(server_query), server_query);
printf (" Query: len %d %s\n", strlen(server_query), server_query);
这些语句使用一组参数或查询选项创建对特定 URI 的 CoAP 请求,以便服务器的 URI 处理程序可以提供对请求的特定响应。对于这个例子,使用的变量是用如下值硬编码的:
char *aszDevName = "DEV-01-203";
char *aszTempoName = "TEMPO-12345";
int iItem = 5;
const char* server_uri = "coap://127.0.0.1/hello";
两个示例程序可以运行在两个独立的终端windows,先启动服务器。尝试客户端三次,第一次使用 "hello" 的 URI,第二次使用 "goodbye" 的 URI,第三次再次使用 "hello" 的 URI,我们看到以下输出。
来自服务器:
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./server
request hello
option len 6
item=5
option len 17
device=DEV-01-203
option len 17
tempo=TEMPO-12345
request hello
option len 6
item=5
option len 17
device=DEV-01-203
option len 17
tempo=TEMPO-12345
来自客户端的终端window:
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./client
Request URI: path 5 hello
Query: len 6 item=5
Query: len 17 device=DEV-01-203
Query: len 17 tempo=TEMPO-12345
Received: {"device": "DEV-01-123", "item" : 0 } -> item = 0
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./client goodbye
Request URI: path 7 goodbye
Query: len 6 item=5
Query: len 17 device=DEV-01-203
Query: len 17 tempo=TEMPO-12345
COAP_RESPONSE_CLASS() unknown.
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./client
Request URI: path 5 hello
Query: len 6 item=5
Query: len 17 device=DEV-01-203
Query: len 17 tempo=TEMPO-12345
Received: {"device": "DEV-01-123", "item" : 1 } -> item = 1
pi@raspberrypi:~/Documents/raspberrypi/coap $
我正在使用 Raspbian 下的 libcoap-dev-1
库和 Raspberry Pi 使用带有简单客户端和简单服务器的库来实现 CoAP 协议。我有一个工作的客户端和一个工作的服务器,现在正在尝试修改服务器,以便它可以接受带有查询字符串的 URI,然后我可以获取 URI 的查询字符串。
我目前正在测试的URI是coap://127.0.0.1/hello?item=1
,它有一个查询参数,?
之后的item=1
。
服务器中的请求处理程序是以下函数,它是一个存根,用于测试将固定响应作为 JSON 文本发送回客户端。这工作正常,客户端收到 JSON 文本并能够使用 Fast JSON 库来解析它。
// header for the libcoap library. it should be in /usr/include/coap
#include <coap/coap.h>
/*
* The resource handler which the libcoap library will invoke when the registered
* URI is specified.
*/
static void
hello_handler(coap_context_t *ctx, struct coap_resource_t *resource,
const coap_endpoint_t *local_interface, coap_address_t *peer,
coap_pdu_t *request, str *token, coap_pdu_t *response)
{
static int iCount = 0;
unsigned char buf[3];
const char* response_data = "{\"device\": \"DEV-01-123\", \"item\" : %d }";
char response_buf[256] = {0};
response->hdr->code = COAP_RESPONSE_CODE(205);
coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
sprintf (response_buf, response_data, iCount);
coap_add_data (response, strlen(response_buf), (unsigned char *)response_buf);
iCount++;
printf (" request %s\n", resource->uri.s);
}
函数末尾的printf()
打印不带查询部分的URI。所以打印的是 hello
而不是 hello?item=1
.
我的问题是如何访问客户端发送的 URI 的查询部分?
用于创建服务器和客户端的 libcoap
函数需要更多步骤作为格式化和检索 URI 和 URI 查询信息的一部分 into/from CoAP 请求。
完整的示例应用程序 client.c 和 server.c 在我的 GitHub 存储库中 https://github.com/RichardChambers/raspberrypi/tree/master/coap。
在服务器端,消息处理程序将使用一个选项迭代器,一个 coap_opt_iterator_t
结构对象,来迭代 coap_pdu_t
结构请求对象的选项。迭代时,服务器将寻找 COAP_OPTION_URI_QUERY
类型的选项,其中包含查询参数,通常是关键字等值对。
所以发布问题的函数 hello_handler()
可以用辅助函数重写,以获取 URI 查询项列表,如下所示:
/*
* The following helper function, printQueryOption(), is used to
* iterate over the list of options looking for query type options
* to the base URI. This is analogous to a web URL that contains
* a question mark followed by options such as:
* http://www.server.com/hello?type=1,id=2345
*
* We will return a value of 1 (true) if we found something or a value
* of 0 (false) if we do not.
*/
static int
printQueryOption (coap_pdu_t *request, coap_opt_iterator_t * popt_iter )
{
int iRet = 0;
coap_opt_t *option;
// iterate over the options looking for queries. If we find one
// then print it and return a value of 1, true, to indicate we
// found one. If we don't find any then return the default value
// of 0, false.
while (option = coap_option_next(popt_iter)) {
// found an option, is it a query option or not.
if (popt_iter->type != COAP_OPTION_URI_QUERY) continue;
// it is a query option so print out the query text.
char xBuff[128] = {0};
strncpy (xBuff, COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option));
printf (" option len %d\n %s \n", COAP_OPT_LENGTH(option), xBuff);
// indicate that we found a query option.
iRet = 1;
break;
}
return iRet;
}
/*
* The resource handler which the libcoap library will invoke when the registered
* URI is specified. This is a simple request handler which will just display some
* of the information from the request.
*/
static void
hello_handler(coap_context_t *ctx, struct coap_resource_t *resource,
const coap_endpoint_t *local_interface, coap_address_t *peer,
coap_pdu_t *request, str *token, coap_pdu_t *response)
{
static int iCount = 0; // a simple count to provide some kind of response data.
unsigned char buf[3];
const char* response_data = "{\"device\": \"DEV-01-123\", \"item\" : %d }";
char response_buf[256] = {0};
// generate a response to this request. we have a hard coded JSON text that
// we are using as a stub for testing.
response->hdr->code = COAP_RESPONSE_CODE(205);
coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
sprintf (response_buf, response_data, iCount);
coap_add_data (response, strlen(response_buf), (unsigned char *)response_buf);
iCount++; // this count is some type of varying data so that we can see things are working.
if (request != NULL) {
// there is a request URI so lets print out the base URI and then
// iterate over the options looking for the Query type options.
coap_opt_iterator_t opt_iter;
printf (" request %s\n", resource->uri.s);
coap_option_iterator_init (request, &opt_iter, COAP_OPT_ALL);
// iterate over the options of the request printing out any
// query text that may exist.
while (printQueryOption (request, &opt_iter));
} else {
printf (" request - NONE\n");
}
}
在客户端,我们将构建我们的请求,添加我们想要包含在请求中的查询,并调用一系列函数 coap_add_option()
,如:
coap_split_uri(server_uri, strlen(server_uri), &uri);
request = coap_new_pdu();
request->hdr->type = COAP_MESSAGE_CON;
request->hdr->id = coap_new_message_id(ctx);
request->hdr->code = get_method;
printf (" Request URI: path %d %s\n", uri.path.length, uri.path.s);
coap_add_option(request, COAP_OPTION_URI_PATH, uri.path.length, uri.path.s);
sprintf (server_query, "item=%d", iItem);
coap_add_option(request, COAP_OPTION_URI_QUERY, strlen(server_query), server_query);
printf (" Query: len %d %s\n", strlen(server_query), server_query);
sprintf (server_query, "device=%s", aszDevName);
coap_add_option(request, COAP_OPTION_URI_QUERY, strlen(server_query), server_query);
printf (" Query: len %d %s\n", strlen(server_query), server_query);
sprintf (server_query, "tempo=%s", aszTempoName);
coap_add_option(request, COAP_OPTION_URI_QUERY, strlen(server_query), server_query);
printf (" Query: len %d %s\n", strlen(server_query), server_query);
这些语句使用一组参数或查询选项创建对特定 URI 的 CoAP 请求,以便服务器的 URI 处理程序可以提供对请求的特定响应。对于这个例子,使用的变量是用如下值硬编码的:
char *aszDevName = "DEV-01-203";
char *aszTempoName = "TEMPO-12345";
int iItem = 5;
const char* server_uri = "coap://127.0.0.1/hello";
两个示例程序可以运行在两个独立的终端windows,先启动服务器。尝试客户端三次,第一次使用 "hello" 的 URI,第二次使用 "goodbye" 的 URI,第三次再次使用 "hello" 的 URI,我们看到以下输出。
来自服务器:
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./server
request hello
option len 6
item=5
option len 17
device=DEV-01-203
option len 17
tempo=TEMPO-12345
request hello
option len 6
item=5
option len 17
device=DEV-01-203
option len 17
tempo=TEMPO-12345
来自客户端的终端window:
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./client
Request URI: path 5 hello
Query: len 6 item=5
Query: len 17 device=DEV-01-203
Query: len 17 tempo=TEMPO-12345
Received: {"device": "DEV-01-123", "item" : 0 } -> item = 0
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./client goodbye
Request URI: path 7 goodbye
Query: len 6 item=5
Query: len 17 device=DEV-01-203
Query: len 17 tempo=TEMPO-12345
COAP_RESPONSE_CLASS() unknown.
pi@raspberrypi:~/Documents/raspberrypi/coap $ ./client
Request URI: path 5 hello
Query: len 6 item=5
Query: len 17 device=DEV-01-203
Query: len 17 tempo=TEMPO-12345
Received: {"device": "DEV-01-123", "item" : 1 } -> item = 1
pi@raspberrypi:~/Documents/raspberrypi/coap $