Citire JSON Stream

Salut!

Am o intrebare legata de citirea unui Json stream.
Eu am nevoie sa citesc un json stream(cu cote, pariuri sportive)
Acest json stream imi vine pe socketul localhost:8992.
In documentatia acestuia, mi se spune ca:

All messages sending to your application will form a JSON stream (no delimiter between messages), so you may need a decoder that support JSON stream. Each message will have a type property to indicate what type it is. You can use this property to decide what to do with the messages.

Eu pana acum, nu am folosit niciodata asa ceva. Mereu m-am “jucat” cu stringuri.
Am gasit pe net libraria asta:

Am instalat-o corespunzator, de asta sunt sigur. Am testat folosind exemplele furnizate.
Dar cand incerc sa o folosesc pe ce am eu nevoie, si anume citirea unui json stream de pe socketul localhost:8992
nu merge.
Nu imi da nici o eroare, nu se intampla pur si simplu nimic.

In exemplul oferit de salsify, se citea un json pur si simplu.
Ca sa citesc de pe socketul meu, am schimbat liniile:

$testfile = dirname(__FILE__) . '/../tests/data/example.json';
$stream = fopen($testfile, 'r');

cu
$stream = fsockopen ('127.0.0.1' , 8992);

Cred ca ar trebui sa fie ok ce am facut.

intrebare
de ce nu citesti json-ul in php cu json_decode() ?

Nu merge. E prea mare. Nu e un string, e un stream. Deci vin mesaje incontinuu, 4-5 pe secunda chiar.
Eu trebuie sa citesc “bucati” din stream, bucati destul de mari incat sa nu crape memoria php-ului.

2 Likes

vezi daca te ajuta

aa: acum am vazut ca este aceeasi biblioteca ca acolo !

Nu inteleg ce ai vrea sa faci cu php.

Trebuie sa faci un buffer, sa salvezi streamul pe o anumita perioada, sa afisezi/salvezi datele care iti trebuie in obiecte/array-uri si sa stergi din buffer ce ai procesat.

1 Like

Salut!

  1. Nu stiu de unde sa incep in a face treaba asta. M-as fi asteptat sa pot face asta cu libraria mai sus mentionata. Nu asta ar fi trebuit sa faca?

  2. Te rog indruma-ma in directia potrivita. Eu am primit de la cei care au imi pun la dispozitie json stream-ul, un exemplu de php.
    Il pun mai jos. Cum as putea sa ma folosesc de asta, si sa folosesc buffere?

PS. Intre timp mai caut pe net, evident, dar un raspuns de la cineva care stie cu ce se mananca bufferele, m-ar ajuta mult.

<?php
function processMessage($message) {
    echo $message;
}
$HOST = "localhost";
$PORT = 8992;

/* Get the IP address for the target host. */
$address = gethostbyname($HOST);

/* Create a TCP/IP socket. */
echo "Attempting to create TCP/IP socket..."; 
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
} else {
    echo "OK.\n";
}

echo "Attempting to connect to '$address' on port '$PORT'...";
$result = socket_connect($socket, $address, $PORT);
if ($result === false) {
    echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
} else {
    echo "OK.\n";
}

$in = "{\"type\":\"SUBSCRIBE\"}";
$out = '';
socket_write($socket, $in, strlen($in));
echo "OK.\n";

echo "Reading response:\n\n";
$buf = '';
$open = 0;

while(true){
    if (false !== ($bytes = socket_recv($socket, $buf, 2048, MSG_WAITALL))) {
        $buf = $buf.$bytes;
        if($bytes[0] == "{"){
            $open+=1;
        }
        if($bytes[0] == "}"){
            $open-=1;
        }
        if($open == 0){
            processMessage($buf);
            $buf = "";
        }
    } else {
        echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($socket)) . "\n";
    }
}

/* close socket */
socket_close($socket);

?>
1 Like

Libraria aceea e construita pentru a o folosi cu fisiere json. La o prima vedere libraria asteapta sa citeasca linii(ii trebuie un ‘\n’ din cand in cand in stream pentru a continua procesarea). In functie de cum e formatat stream-ul json, e posibil sa nu ai asa ceva. Ai putea sa incerci sa inlocuiesti ‘\n’ cu ‘}’ folosind constructorul:

$parser = new \JsonStreamingParser\Parser($stream, $listener, "}");

In cazul asta posibil sa trebuiasca sa adaugi la buffer caracterul folosit pe post de sfarsit de linie (stream_get_line parca nu intoarce si caracterul de sfarsit de linie). Sau sa folosesti alt caracter pe post de sfarsit de linie care nu conteaza in json(‘spatiu’ daca este folosit in stream).
Daca tot nu merge, posibil sa trebuiasca sa modifici putin libraria pentru cazul tau de folosinta.
Functia la care cred ca trebuie sa te uiti este:

2 Likes

Poti sa folosesti si exemplul dat de ei. tot ce trebuie sa faci este sa completezi functia processMessage:

function processMessage($message) {
    // $message aici contine un obiect codat json
    $obj = json_decode($message);
    // aici extragi ce informatii te intereseaza din $obj
}

La o vizionare mai atenta, nu prea are nici o logica while-ul din exemplul lor. Ar trebui sa fie:

$obj_json = '';
while(true){
    if (false !== ($bytes = socket_recv($socket, $buf, 2048, MSG_WAITALL))) {
        for ($i = 0; $i < $bytes; $i++) {
           $obj_json .= $buf[$i];
           if($buf[$i] == "{"){
               $open+=1;
           }
           if($buf[$i] == "}"){
               $open-=1;
           }
           if($open == 0){
              processMessage($obj_json);
              $obj_json = "";
           }
        }
    } else {
        echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($socket)) . "\n";
    }
}

N-am mai folosit de mult PHP, asa ca nu pot sa garantez ca sintaxa de mai sus e 100% corecta. Te rog sa verifici inainte sa folosesti.

1 Like