如何在 C++ 中从 HTTP 响应中提取 JSON 数据?

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

我正在尝试制作一个客户端-服务器应用程序,并且我正在尝试通过 REST API 将数据从我的服务器发送到我的客户端。在服务器端,我将 Django 与 Django REST Framework 一起使用,我配置了代码来处理请求,如下所示:

from .models import Song
from .serializers import SongSerializer

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status

@api_view(['GET', 'POST'])
def song_list(request, format=None):
    # get all Songs
    # serialize
    # return JSON
    if request.method == 'GET':
        songs = Song.objects.all()
        serializer = SongSerializer(songs, many=True)
        return Response(serializer.data)

    if request.method == 'POST':
        serializer = SongSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)

@api_view(['GET', 'PUT', 'DELETE'])
def song_detail(request, id, format=None):
    try:
        song = Song.objects.get(pk=id)
    except Song.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SongSerializer(song)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = SongSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        song.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

当我使用 python 使用 API 时,它可以很容易地使用这段代码(我根据需要获取 JSON 数据)

import requests

response = requests.get("http://127.0.0.1/api/")

print(response.json)

但是从客户端,我在 GET 请求中得到的只是 HTTP 响应标头。这是我的客户端代码:

/* Sockets Example
 * Copyright (c) 2016-2020 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "mbed-trace/mbed_trace.h"

#include "wifi_helper.h"


class SocketInterface {
    static constexpr size_t MAX_NUMBER_OF_ACCESS_POINTS = 10;
    static constexpr size_t MAX_MESSAGE_RECEIVED_LENGTH = 100;
    static constexpr size_t REMOTE_PORT = 80; // standard HTTP port

public:
    SocketInterface() : net(NetworkInterface::get_default_instance())
    {
    }

    ~SocketInterface()
    {
        if (net) {
            net->disconnect();
        }
    }

    void run()
    {
        if (!net) {
            printf("Error! No network interface found.\r\n");
            return;
        }

        /* if we're using a wifi interface run a quick scan */
        if (net->wifiInterface()) 
        {
            /* the scan is not required to connect and only serves to show visible access points */
            wifi_scan();

            /* in this example we use credentials configured at compile time which are used by
             * NetworkInterface::connect() but it's possible to do this at runtime by using the
             * WiFiInterface::connect() which takes these parameters as arguments */
        }

        /* connect will perform the action appropriate to the interface type to connect to the network */

        printf("Connecting to the network...\r\n");

        nsapi_size_or_error_t result = net->connect();
        if (result != 0) 
        {
            printf("Error! net->connect() returned: %d\r\n", result);
            return;
        }

        print_network_info();

        /* opening the socket only allocates resources */
        result = socket.open(net);
        if (result != 0) 
        {
            printf("Error! socket.open() returned: %d\r\n", result);
            return;
        }

        /* now we have to find where to connect */

        SocketAddress* address = new SocketAddress("192.168.100.88", 80);

        // if (!resolve_hostname(address))
        // {
        //     return;
        // }

        // address.set_port(REMOTE_PORT);

        /* we are connected to the network but since we're using a connection oriented
         * protocol we still need to open a connection on the socket */

        printf("Opening connection to remote port %d\r\n", REMOTE_PORT);

        result = socket.connect(*address);
        if (result != 0)
        {
            printf("Error! socket.connect() returned: %d\r\n", result);
            return;
        }

        /* exchange an HTTP request and response */

        if (!send_http_request())
        {
            return;
        }

        if (!receive_http_response())
        {
            return;
        }

        printf("Demo concluded successfully \r\n");
    }

private:
    bool resolve_hostname(SocketAddress &address)
    {
        const char hostname[] = MBED_CONF_APP_HOSTNAME;

        /* get the host address */
        printf("\nResolve hostname %s\r\n", hostname);
        nsapi_size_or_error_t result = net->gethostbyname(hostname, &address);
        if (result != 0)
        {
            printf("Error! gethostbyname(%s) returned: %d\r\n", hostname, result);
            return false;
        }

        printf("%s address is %s\r\n", hostname, (address.get_ip_address() ? address.get_ip_address() : "None") );

        return true;
    }

    bool send_http_request()
    {
        /* loop until whole request sent */
        const char buffer[] = "GET /api/ HTTP/1.1\r\n"
                              "\r\n";

        nsapi_size_t bytes_to_send = strlen(buffer);
        nsapi_size_or_error_t bytes_sent = 0;

        printf("\r\nSending message: \r\n%s", buffer);

        while (bytes_to_send)
        {
            bytes_sent = socket.send(buffer + bytes_sent, bytes_to_send);
            if (bytes_sent < 0)
            {
                printf("Error! socket.send() returned: %d\r\n", bytes_sent);
                return false;
            }
            else
            {
                printf("sent %d bytes\r\n", bytes_sent);
            }

            bytes_to_send -= bytes_sent;
        }

        printf("Complete message sent\r\n");

        return true;
    }

    bool receive_http_response()
    {
        char buffer[MAX_MESSAGE_RECEIVED_LENGTH];
        int remaining_bytes = MAX_MESSAGE_RECEIVED_LENGTH;
        int received_bytes = 0;

        /* loop until there is nothing received or we've ran out of buffer space */
        nsapi_size_or_error_t result = remaining_bytes;
        while (result > 0 && remaining_bytes > 0)
        {
            result = socket.recv(buffer + received_bytes, remaining_bytes);
            if (result < 0)
            {
                printf("Error! socket.recv() returned: %d\r\n", result);
                return false;
            }

            received_bytes += result;
            remaining_bytes -= result;
        }

        /* the message is likely larger but we only want the HTTP response code */
        printf("received: %s\r\n\r\n", buffer);
        // printf("received %d bytes:\r\n%.*s\r\n\r\n", received_bytes, strstr(buffer, "\n") - buffer, buffer);

        return true;
    }

    void wifi_scan()
    {
        WiFiInterface *wifi = net->wifiInterface();

        WiFiAccessPoint ap[MAX_NUMBER_OF_ACCESS_POINTS];

        /* scan call returns number of access points found */
        int result = wifi->scan(ap, MAX_NUMBER_OF_ACCESS_POINTS);

        if (result <= 0) {
            printf("WiFiInterface::scan() failed with return value: %d\r\n", result);
            return;
        }

        printf("%d networks available:\r\n", result);

        for (int i = 0; i < result; i++) {
            printf("Network: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\r\n",
                   ap[i].get_ssid(), get_security_string(ap[i].get_security()),
                   ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2],
                   ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5],
                   ap[i].get_rssi(), ap[i].get_channel());
        }
        printf("\r\n");
    }

    void print_network_info()
    {
        /* print the network info */
        SocketAddress a;
        net->get_ip_address(&a);
        printf("IP address: %s\r\n", a.get_ip_address() ? a.get_ip_address() : "None");
        net->get_netmask(&a);
        printf("Netmask: %s\r\n", a.get_ip_address() ? a.get_ip_address() : "None");
        net->get_gateway(&a);
        printf("Gateway: %s\r\n", a.get_ip_address() ? a.get_ip_address() : "None");
    }

private:

    NetworkInterface *net;
    TCPSocket socket;

};

int main() 
{
    printf("\n");
    printf("************************************************************\n");
    printf("***   STM32 IoT Discovery kit for STM32L475 MCU          ***\n");
    printf("***         WIFI Web Server demonstration                ***\n");
    printf("***             Update the LED status                    ***\n");
    printf("************************************************************\n");
    

    SocketInterface *sockIf = new SocketInterface();
    MBED_ASSERT(sockIf);
    sockIf->run();

    return 0;
}

我收到的缓冲区是这样的:

Serial Monitor Data

我在 B-L475VG-IOT01A 板上使用 MBED 操作系统。

任何帮助将不胜感激!

我已经发出了 GET 请求,但我不知道如何访问 JSON 数据

python c++ stm32 mbed
© www.soinside.com 2019 - 2024. All rights reserved.