CoAP客户端如何接收超过1024的大数据

问题描述 投票:0回答:1

/* 我正在从 CoAP 服务器CoAP 客户端 发送超过 1024 大小的响应。但是,我无法在 CoAP 客户端中接收完整的数据。我只能接收 1024 大小的数据。

用于在服务器中发送较大数据的API: coap_add_data_large_response()

客户端用于接收较大数据的API: coap_get_data_large()

但是,在wireshark中,完整的数据以2个块或pdu的形式发送。例如,如果数据大小为1224,则发送的第一组数据为1024大小,发送的第二组数据为200大小。但我无法收到完整的数据。

请您指导一下,如何在CoAP客户端中接收完整的数据(超过1024)。

如何使用此 API coap_block_build_body() 将多个块或 pdu 的数据收集为单个大数据(超过 1024)。 */

/***********CoAP Server Code***************/
    
#include <coap3/coap.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
 
#define GET_CMD           "get_details"
    
int resolve_address(const char *host, const char *service, coap_address_t *dst) 
{
    
        struct addrinfo *res, *ainfo;
        struct addrinfo hints;
        int error, len = -1;
    
        memset(&hints, 0, sizeof(hints));
        memset(dst, 0, sizeof(*dst));
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_family = AF_UNSPEC;
    
        error = getaddrinfo(host, service, &hints, &res);
    
        if (error != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
            return error;
        }
    
        for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
            switch (ainfo->ai_family) {
            case AF_INET6:
            case AF_INET:
                len = dst->size = ainfo->ai_addrlen;
                memcpy(&dst->addr.sin6, ainfo->ai_addr, dst->size);
            default:
                ;
            }
        }
    
        freeaddrinfo(res);
        return len;
    }
    
    static void resource_handler(struct coap_resource_t *resource,
            struct coap_session_t *session, const struct coap_pdu_t *request,
            const struct coap_string_t *query, struct coap_pdu_t *response) {
    
        uint8_t *payloadBuffer;
        size_t payload_len;
        size_t offset = 0;
        size_t total = 0;
        (void) resource;
        uint8_t res[2048] =
                "[{\"id\":\"0001\",\"type\":\"donut\",\"name\":\"Cake\",\"ppu\":0.55,\"batters\":{\"batter\":[{\"id\":\"1001\",\"type\":\"Regular\"},{\"id\":\"1002\",\"type\":\"Chocolate\"},{\"id\":\"1003\",\"type\":\"Blueberry\"},{\"id\":\"1004\",\"type\":\"Devil's Food\"}]},\"batters\":{\"batter\":[{\"id\":\"1001\",\"type\":\"Regular\"},{\"id\":\"1002\",\"type\":\"Chocolate\"},{\"id\":\"1003\",\"type\":\"Blueberry\"},{\"id\":\"1004\",\"type\":\"Devil's Food\"}]},\"batters\":{\"batter\":[{\"id\":\"1001\",\"type\":\"Regular\"},{\"id\":\"1002\",\"type\":\"Chocolate\"},{\"id\":\"1003\",\"type\":\"Blueberry\"},{\"id\":\"1004\",\"type\":\"Devil's Food\"}]},\"batters\":{\"batter\":[{\"id\":\"1001\",\"type\":\"Regular\"},{\"id\":\"1002\",\"type\":\"Chocolate\"},{\"id\":\"1003\",\"type\":\"Blueberry\"},{\"id\":\"1004\",\"type\":\"Devil's Food\"}]},\"batters\":{\"batter\":[{\"id\":\"1001\",\"type\":\"Regular\"},{\"id\":\"1002\",\"type\":\"Chocolate\"},{\"id\":\"1003\",\"type\":\"Blueberry\"},{\"id\":\"1004\",\"type\":\"Devil's Food\"}]},\"topping\":[{\"id\":\"5001\",\"type\":\"None\"},{\"id\":\"5002\",\"type\":\"Glazed\"},{\"id\":\"5005\",\"type\":\"Sugar\"},{\"id\":\"5007\",\"type\":\"Powdered Sugar\"},{\"id\":\"5006\",\"type\":\"Chocolate with Sprinkles\"},{\"id\":\"5003\",\"type\":\"Chocolate\"},{\"id\":\"5004\",\"type\":\"Maple\"}]},{\"id\":\"0002\",\"type\":\"donut\",\"name\":\"Raised\",\"ppu\":0.55,\"batters\":{\"batter\":[{\"id\":\"1001\",\"type\":\"Regular\"}]},\"topping\":[{\"id\":\"5001\",\"type\":\"None\"},{\"id\":\"5002\",\"type\":\"Glazed\"},{\"id\":\"5005\",\"type\":\"Sugar\"},{\"id\":\"5003\",\"type\":\"Chocolate\"},{\"id\":\"5004\",\"type\":\"Maple\"}]},{\"id\":\"0003\",\"type\":\"donut\",\"name\":\"Old Fashioned\",\"ppu\":0.55,\"batters\":{\"batter\":[{\"id\":\"1001\",\"type\":\"Regular\"},{\"id\":\"1002\",\"type\":\"Chocolate\"}]},\"topping\":[{\"id\":\"5001\",\"type\":\"None\"},{\"id\":\"5002\",\"type\":\"Glazed\"},{\"id\":\"5003\",\"type\":\"Chocolate\"},{\"id\":\"5004\",\"type\":\"Maple\"}]}]";
    
        /* API to receive small data upto 1024 bytes*/
        coap_get_data(request, &payload_len, (const uint8_t**) &payloadBuffer);
    
        // /* API to receive large data more than 1024 bytes*/
        // coap_get_data_large(request, &payload_len, (const uint8_t **)&payloadBuffer, &offset, &total);
    
        // printf("getHwInfoHandler Query from client: \n%s\n\n", payloadBuffer);
        // printf("payload_len %ld\n", payload_len);
    
        // coap_add_data_large_request(session, request, strlen(res), (const uint8_t *)res, NULL, NULL);
    
        const uint8_t *cmd = coap_resource_get_uri_path(resource)->s;
        printf("Request received from service tool: %s\n\n", cmd);
    
    #if 1
    
        if (cmd != NULL) {
            if ((strcmp(cmd, GET_CMD)) == 0) {
                memset(&payloadBuffer, 0, payload_len);
                coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
    
                printf("json sent to client: \n%s\n\n", res);
                printf("strlen(res) %ld\n", strlen(res));
    
                // coap_add_data(response, strlen(res), (const uint8_t *)res);
                // coap_add_data_large_request(session, request, strlen(res), (const uint8_t *)res, NULL, NULL);
                // coap_add_data_large_request(session, request2, 6, "buffer", NULL, NULL);
    
                // coap_add_data_large_response(resource,session,request,response,query,0,-1,0,strlen(res), (const uint8_t *)res,NULL,NULL);
    
                int retval = coap_add_data_large_response(resource, session,
                        request, response, query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
                        strlen(res), (const uint8_t*) res, NULL, NULL);
                // int retval = coap_add_data_large_response(resource, session, request, response, query, COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON, 1, 0, strlen(res), (const uint8_t *)res,NULL,NULL);
                printf("coap_add_data_large_response():retval: %d\n", retval);
            }
        }
    
    #endif
    }
    
    int main() {
        coap_context_t *ctx;
        coap_endpoint_t *endpoint;
        coap_resource_t *resource;
        coap_resource_t *resource2;
        coap_resource_t *resource3;
        coap_address_t listen_addr;
        coap_str_const_t *ruri = coap_make_str_const("get_details");
    
        coap_startup();
    
        resolve_address("127.0.0.1", "5683", &listen_addr); //127.0.0.1 //192.168.1.6
    
        ctx = coap_new_context(NULL);
    
        coap_new_endpoint(ctx, &listen_addr, COAP_PROTO_UDP);
    
        resource = coap_resource_init(ruri, 0);
        coap_context_set_block_mode(ctx,
                COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
        // coap_context_set_block_mode(ctx, COAP_BLOCK_USE_LIBCOAP);                 
        coap_register_handler(resource, COAP_REQUEST_PUT, resource_handler);
        coap_add_resource(ctx, resource);
    
        while (1) {
            int result = coap_io_process(ctx, COAP_IO_WAIT);
        }
    
        coap_free_context(ctx);
        coap_cleanup();
    
    return EXIT_`SUCCESS;
    }

/***********CoAP Client Code***************/
    
    #include <coap3/coap.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    
    static int have_response = 0;
    
    char *buffer;  //  = "testing 123";
    
    int resolve_address(const char *host, const char *service, coap_address_t *dst) {
    
    struct addrinfo *res, *ainfo;
    struct addrinfo hints;
    int error, len = -1;
    
    memset(&hints, 0, sizeof(hints));
    memset(dst, 0, sizeof(*dst));
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_family = AF_UNSPEC;
    
    error = getaddrinfo(host, service, &hints, &res);
    
    if (error != 0) {
        printf("getaddrinfo: %s\n", gai_strerror(error));
        return error;
    }
    
    for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
        switch (ainfo->ai_family) {
        case AF_INET6:
        case AF_INET:
            len = dst->size = ainfo->ai_addrlen;
            memcpy(&dst->addr.sin6, ainfo->ai_addr, dst->size);
        default:
            ;
        }
    }
    
    freeaddrinfo(res);
    return len;
    }
    
    coap_response_t response_handler(struct coap_session_t *session,
        const struct coap_pdu_t *request, const struct coap_pdu_t *response,
        const coap_mid_t mid) {
    size_t payload_len;
    size_t coap_ret;
    uint8_t *payloadBuffer = NULL;
    size_t offset = 0;
    size_t total = 0;
    size_t size;
    
    // Get the payload (data) from the request
    // coap_ret = coap_get_data(response, &payload_len, &payloadBuffer);
    
    #if 1
    /* API to receive large data more than 1024 bytes*/
    coap_get_data_large(response, &payload_len, (const uint8_t**) &payloadBuffer,
            &offset, &total);
    
    printf("Response from server: \n%s\n\n", payloadBuffer);
    printf("payload_len: %ld\n", payload_len);
    printf("offset: %ld\n", offset);
    printf("total: %ld\n", total);
    #endif
    memset(payloadBuffer, '\0', payload_len);
    }
    
    int main() {
    printf("CoAP_client\n");
    coap_context_t *ctx = NULL;
    coap_session_t *session = NULL;
    coap_pdu_t *request = NULL;
    coap_address_t server_address;
    coap_address_t client_address;
    coap_optlist_t *optlist = NULL;
    coap_pdu_t *response = NULL;
    unsigned char *response_data = NULL;
    size_t response_length = 0;
    long file_size;
    
    coap_startup();
    
    ctx = coap_new_context(NULL);
    if (!ctx) {
        return 0;
    }
    
    coap_context_set_block_mode(ctx,
            COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
    // coap_context_set_block_mode(ctx, COAP_BLOCK_USE_LIBCOAP);
    resolve_address("127.0.0.1", "5683", &server_address);  //127.0.0.1
    
    session = coap_new_client_session(ctx, NULL, &server_address, COAP_PROTO_UDP);
    
    if (!session) {
        printf("Failed to create client session\n");
        coap_free_context(ctx);
        return EXIT_FAILURE;
    }
    
    coap_register_response_handler(ctx, response_handler);
    
    request = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_PUT,
            coap_new_message_id(session), coap_session_max_pdu_size(session));
    
    coap_add_option(request, COAP_OPTION_URI_PATH, strlen("get_details"),
            (const uint8_t*) "get_details");
    
    printf("******* get_details *******\n\n\n");
    
    if (coap_send(session, request) == -1) {
        printf("send failed\n");
        coap_free_context(ctx);
        return EXIT_FAILURE;
    } else {
        printf("send success\n");
    }
    
    coap_io_process(ctx, COAP_IO_WAIT);
    
    coap_session_release(session);
    coap_free_context(ctx);
    coap_cleanup();
    
    return EXIT_SUCCESS;
    }
json client-server coap
1个回答
0
投票

CoAP 将更大的有效负载拆分为单个请求/响应对。为此,RFC7959 扩展了 RFC 7252 中的基本规范。通常称为“块式”传输。因此,响应包含 CoAP 选项,在本例中为 BLOCK-2 选项,它指示按块传输。然后,客户端被认为请求下一个块,直到服务器在该 BLOCK-2 选项中报告传输已完成。

这可能取决于您使用的客户端库,但通常使用“blockwise”搜索会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.