首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在libcoap coap服务器获取响应处理程序中,如何访问对URI的查询添加?

在libcoap coap服务器获取响应处理程序中,如何访问对URI的查询添加?
EN

Stack Overflow用户
提问于 2017-12-27 06:24:12
回答 1查看 1.5K关注 0票数 1

我正在使用Raspbian下的libcoap-dev-1库和一个Raspberry Pi,使用这个库和一个简单的客户机和简单的服务器来实现CoAP协议。我有一个正常工作的客户机和一个正常工作的服务器,现在正在尝试修改服务器,以便它可以接受包含查询字符串的URI,然后我可以获取该URI的查询字符串。

我目前正在测试的URI是coap://127.0.0.1/hello?item=1,它有一个查询参数,即?之后的item=1

服务器中的请求处理程序是以下函数,它是一个存根,用于测试将录制的响应以JSON文本形式发送回客户端。这可以很好地工作,客户端接收JSON文本,并能够使用Fast JSON库来解析它。

代码语言:javascript
复制
// 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的查询部分?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-29 10:48:54

作为格式化URI和从CoAP请求中检索URI和URI查询信息的一部分,用于创建服务器和客户机的libcoap函数还需要几个步骤。

完整的示例应用程序client.c和server.c在我位于https://github.com/RichardChambers/raspberrypi/tree/master/coap的GitHub存储库中。

在服务器端,消息处理程序将使用一个选项迭代器(一个coap_opt_iterator_t结构对象)来迭代coap_pdu_t结构请求对象的选项。在迭代时,服务器将查找COAP_OPTION_URI_QUERY类型的选项,该选项将包含查询参数,通常是关键字相等值对。

因此,可以使用助手函数重写发布的问题的函数hello_handler(),以获得URI查询项的列表,如下所示:

代码语言:javascript
复制
/*
 * 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()调用,如下所示:

代码语言:javascript
复制
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的服务器处理程序可以向请求提供特定的响应。在本例中,使用的变量使用如下所示的值进行硬编码:

代码语言:javascript
复制
char *aszDevName = "DEV-01-203";
char *aszTempoName = "TEMPO-12345";
int  iItem = 5;

const char*       server_uri = "coap://127.0.0.1/hello";

这两个示例程序可以在两个单独的终端窗口中运行,首先启动服务器。尝试客户机三次,第一次使用URI "hello",第二次使用URI“告别”,第三次使用URI "hello“,我们将看到以下输出。

从服务器:

代码语言:javascript
复制
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 

在客户端的终端窗口中:

代码语言:javascript
复制
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 $ 
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47984333

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档