Как читать весь HTTP-пакет в буфере в C [duplicate]

Intro

Сначала у вас есть строка. JSON не является массивом, объектом или структурой данных. JSON - текстовый формат сериализации - так что причудливая строка, но все же просто строка. Декодируйте его в PHP с помощью json_decode() .

 $data = json_decode($json);

В нем вы можете найти:

Это то, что может быть закодировано в JSON. Или, точнее, это версии PHP, которые могут быть закодированы в JSON.

В них нет ничего особенного. Они не являются объектами JSON или массивами JSON. Вы расшифровали JSON - теперь у вас есть основные повседневные типы PHP .

Объекты будут экземплярами stdClass , встроенным классом, который просто generic thing , что здесь не важно.


Доступ к свойствам объекта

Вы получаете доступ к свойствам одного из этих объектов так же, как и для публичных нестатических свойств любого другого объекта, например $object->property.

$json = '
{
    "type": "donut",
    "name": "Cake"
}';

$yummy = json_decode($json);

echo $yummy->type; //donut

Доступ к элементам массива

Доступ к элементам одного из этих массивов осуществляется так же, как и для любого другой массив, например $array[0] .

$json = '
[
    "Glazed",
    "Chocolate with Sprinkles",
    "Maple"
]';

$toppings = json_decode($json);

echo $toppings[1]; //Chocolate with Sprinkles

Итерации над ним с помощью foreach .

foreach ($toppings as $topping) {
    echo $topping, "\n";
}

Глазурованный Шоколад с спринклерами Maple

blockquote>

Или беспорядок с любой из встроенных функций bazillion [].


Доступ к вложенные элементы

Свойства объектов и элементов массивов могут быть больше объектов и / или массивов - вы можете просто продолжать доступ к своим свойствам и членам как обычно, например $object->array[0]->etc.

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}';

$yummy = json_decode($json);

echo $yummy->toppings[2]->id; //5004

Передача true в качестве второго аргумента в json_decode ()

Когда вы это сделаете, вместо объектов вы получите ассоциативные массивы - массивы со строками для ключей. Снова вы получаете доступ к их элементам, как обычно, например. $array['key'].

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}';

$yummy = json_decode($json, true);

echo $yummy['toppings'][2]['type']; //Maple

Не знаю, как структурированы данные

Прочитайте документацию, независимо от того, получение JSON из.

Посмотрите на JSON - где вы видите фигурные скобки {}, ожидайте объект, где вы видите квадратные скобки [], ожидаете массив.

Нажмите декодированные данные с помощью print_r() :

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}';

$yummy = json_decode($json);

print_r($yummy);

и проверьте вывод:

stdClass Object
(
    [type] => donut
    [name] => Cake
    [toppings] => Array
        (
            [0] => stdClass Object
                (
                    [id] => 5002
                    [type] => Glazed
                )

            [1] => stdClass Object
                (
                    [id] => 5006
                    [type] => Chocolate with Sprinkles
                )

            [2] => stdClass Object
                (
                    [id] => 5004
                    [type] => Maple
                )

        )

)

Он расскажет вам, где у вас есть объекты, где у вас есть массивы, а также имена и значения их членов.

Если вы можете только дойти до него до того, как потеряетесь, зайдите так далеко и нажмите , что с print_r():

print_r($yummy->toppings[0]);
stdClass Object
(
    [id] => 5002
    [type] => Glazed
)

Разбить проблему на части, которые легче обернуть вокруг головы.


json_decode() возвращает null

Это происходит потому, что либо:

  1. JSON полностью состоит именно из этого, null.
  2. JSON is недействителен - проверьте результат json_last_error_msg или введите его через JSONLi nt .
  3. Он содержит элементы, вложенные в глубину более 512 уровней. Эта максимальная глубина по умолчанию может быть переопределена путем передачи целого числа в качестве третьего аргумента в json_decode() .

Если вам нужно изменить максимальную глубину, вы, вероятно, решение неправильной проблемы. Узнайте, почему вы получаете такие глубоко вложенные данные (например, у службы, к которой вы обращаетесь, у которой возникает JSON, есть ошибка) и получить это, чтобы этого не произошло.


Имя свойства объекта содержит специальный символ

Иногда у вас будет имя свойства объекта, которое содержит нечто вроде дефиса - или знака @, которое не может использоваться в литеральном идентификаторе. Вместо этого вы можете использовать строковый литерал в фигурных скобках для его адресации.

$json = '{"@attributes":{"answer":42}}';
$thing = json_decode($json);

echo $thing->{'@attributes'}->answer; //42

Если у вас есть свойство integer as: Как получить доступ к свойствам объекта с именами типа целых чисел? как ссылка.


Кто-то поставил JSON в ваш JSON

Это смешно, но это происходит - JSON закодирован как строка в вашем JSON. Декодирование, доступ к строке как обычно, декодирование , которое , и, в конечном счете, доступ к тому, что вам нужно.

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": "[{ \"type\": \"Glazed\" }, { \"type\": \"Maple\" }]"
}';

$yummy = json_decode($json);
$toppings = json_decode($yummy->toppings);

echo $toppings[0]->type; //Glazed

Данные не помещаются в память

Если ваш JSON слишком большой для json_decode(), чтобы обрабатывать сразу, все начинает становиться сложным. См. Также:


Как отсортировать его

См.: Ссылка: все основные способы сортировки массивов и данных в PHP .

1
задан Remy Lebeau 27 April 2013 в 01:21
поделиться

1 ответ

Вы вызываете recv() в цикле до тех пор, пока сокет не отключится или не сработает (и неправильно записал полученные данные в ваш поток), сохранив все необработанные данные в вашем буфере char*. Это неверный способ чтения HTTP-ответа, особенно если используются HTTP-алименты (в этом случае в конце ответа не произойдет отключение). Вы должны следовать правилам, изложенным в RFC 2616 . А именно:

  1. Прочитать до тех пор, пока не будет встречена последовательность "\r\n\r\n". Пока не читайте байты.
  2. Проанализируйте полученные заголовки согласно правилам в RFC 2616 Раздел 4.4 . Они сообщают вам фактический формат оставшихся данных ответа.
  3. Прочитайте данные в формате, открытом в # 2.
  4. Проверьте полученные заголовки на наличие заголовка Connection: close если ответ использует HTTP 1.1 или отсутствие заголовка Connection: keep-alive, если ответ использует HTTP 0.9 или 1.0. Если обнаружено, закройте конец соединения сокета, потому что сервер закрывает его конец. В противном случае, держите соединение открытым и повторно использовать его для последующих запросов (если вы не сделали это с помощью соединения, и в этом случае его закрыть).
  5. Обработать полученные данные по мере необходимости.

Короче говоря, вам нужно сделать что-то более похожее на это (псевдокод):

string headers[];
byte data[];

string statusLine = read a CRLF-delimited line;
int statusCode = extract from status line;
string responseVersion = extract from status line;

do
{
    string header = read a CRLF-delimited line;
    if (header == "") break;
    add header to headers list;
}
while (true);

if ( !((statusCode in [1xx, 204, 304]) || (request was "HEAD")) )
{
    if (headers["Transfer-Encoding"] ends with "chunked")
    {
        do
        {
            string chunk = read a CRLF delimited line;
            int chunkSize = extract from chunk line;
            if (chunkSize == 0) break;

            read exactly chunkSize number of bytes into data storage;

            read and discard until a CRLF has been read;
        }
        while (true);

        do
        {
            string header = read a CRLF-delimited line;
            if (header == "") break;
            add header to headers list;
        }
        while (true);
    }
    else if (headers["Content-Length"] is present)
    {
        read exactly Content-Length number of bytes into data storage;
    }
    else if (headers["Content-Type"] == "multipart/byteranges")
    {
        string boundary = extract from Content-Type header;
        read into data storage until terminating boundary has been read;
    }
    else
    {
        read bytes into data storage until disconnected;
    }
}

if (!disconnected)
{
    if (responseVersion == "HTTP/1.1")
    {
        if (headers["Connection"] == "close")
            close connection;
    }
    else
    {
        if (headers["Connection"] != "keep-alive")
            close connection;
    }
}

check statusCode for errors;
process data contents, per info in headers list;
6
ответ дан Remy Lebeau 20 August 2018 в 16:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: