2010-06-27 4 views
2

J'essaie d'ouvrir une connexion à une URL qui enverra périodiquement sur un objet JSON. Je sais que je dois utiliser URLStream et certains rappels d'événements, mais je suis dans l'ignorance quand il s'agit de savoir comment fonctionnent les flux de données, ou le flux général des opérations. Supposons que je sache comment ouvrir la connexion et envoyer les en-têtes de demande corrects. Tout d'abord, un code pertinent:Interrogation longue avec URLStream dans ActionScript - comment savoir quand faire quelque chose avec les données?

stream = new URLStream(); 
stream.addEventListener(ProgressEvent.PROGRESS, dataReceived); 
stream.load(request); 

private function dataReceived(pe:ProgressEvent):void 
{ 
    //now what? 
} 

Si le serveur gicle objets JSON, comment puis-je savoir arrêter de lire un objet complet et de passer à une autre fonction? À quelle fréquence dataReceived est-il appelé? Lorsque le serveur envoie quelque chose, donne-t-il une indication de la taille du JSON pour que vous sachiez quand arrêter? Après avoir lu plusieurs extraits de code du monde Internet, je suis déterminé qu'ils seront les principaux acteurs de cette opération:

pe.bytesLoaded
stream.readUTFBytes (longueur: String)

et peut-être pe.bytesTotal

Je suppose que je ne sais pas comment les utiliser ensemble. Est-ce que bytesTotal est la taille totale attendue de l'objet JSON complet entrant? Je sais si peu de chose à ce sujet que je ne sais vraiment pas quoi demander, alors je lance juste des questions là-bas d'une manière désemparée. J'ai lu http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/net/URLStream.html mais l'exemple de code est un squelette de callbacks donc ce n'est pas utile.

J'espère avoir été clair avec ma (mes) question (s), et merci!

Edit: une seule entrée JSON se termine par un retour chariot \ r

Répondre

1

Je suis en train de comprendre votre question. Si l'explication ci-dessous s'écarte de la vôtre, ignorez-la.

Ceci est un peu bas niveau sur la mise en mémoire tampon de protocole. Vous pouvez utiliser des bibliothèques tierces pour transférer json sur as3 en tant que tel, vous pouvez les utiliser (ex: http://code.google.com/p/as3corelib etc.)

Les données que vous recevez à votre client peuvent être fragmentées ou vous pouvez les obtenir toutes en même temps. Donc, afin de garder une trace de la taille des données (quantité de données que vous recevez), vous devez savoir la taille du serveur de données envoie. Pour ce faire, nous codons généralement les premiers octets (généralement 4 octets) de données avec la taille des données complètes. Cela peut changer en fonction du protocole accepté par le client et le serveur.

data = « < 4 octets> < reste des données> »

Donc, une fois que vous obtenez la taille des données du serveur envoie, vous devez garder une mémoire tampon interne pour recueillir les données jusqu'à ce qu'il reçoive la compléter les données.

Je vais vous dire comment vous pouvez faire ce actionscript. Cela a été pris de

http://code.google.com/p/cave/source/browse/trunk/cave/wave/org/cestum/cave/presenter/rpc/CaveSocket.as

J'ai ajouté des commentaires pour votre compréhension ...

   private function onResponse(e:ProgressEvent):void{ 
        trace("Recieved Response"); 
        //InputBuffer is socket buffer 
        if (inputBuffer.bytesAvailable == 0) 
          inputBuffer.clear(); 

        //copy all bytes from socket buffer, to internal buffer - this way you avoid working on socket buffer internally 
        //and have more control on the pulling data your way. Because server keeps on appending data to socket buffer, 
        //you may lose control 
        readBytes(inputBuffer, inputBuffer.length, bytesAvailable); 

        //AS3 is single threaded, we'll create a new event for our data 
        //processing so that socket buffers its data from server seperately. 
        dispatchEvent(new Event("DataComplete")); 
      } 

      //DataComplete Event 
      function onCompleteData(event:Event):void { 
        trace("Complete Data"); 
        //We havent got the requires data size from server 
        if (requiredSize == -1) { 
          //Look for first four bytes - that has our data size. 
          if (inputBuffer.bytesAvailable < 4) { 

            return; 
          } 
          var sizeBuffer:ByteArray = new ByteArray(); 
          inputBuffer.readBytes(sizeBuffer,0 , 4);   
          var ipStream1:CodedInputStream = CodedInputStream.newInstance(sizeBuffer); 
          requiredSize = ipStream1.readRawLittleEndian32(); 
        } 
        if (requiredSize == -1) return; 

        trace("Req: " + requiredSize + " buffer_length: " + buffer.length + "  bytes_Available: " + inputBuffer.bytesAvailable + "  bytes_Position: " + inputBuffer.position); 

        //Now you know the size of data server is sending... just extract that amount of data from socket buffer to internal buffer. 


        if ((requiredSize - buffer.length) > inputBuffer.bytesAvailable) { 
          inputBuffer.readBytes(buffer,buffer.length , inputBuffer.bytesAvailable); 
          return; 
        } else { 
          inputBuffer.readBytes(buffer, buffer.length , (requiredSize - buffer.length)); 
        } 
        trace("Before processing: " + buffer.length); 

       ...Process your data here.... 


        requiredSize = -1; 
        lastReadByte = -1; 
        buffer = new ByteArray(); 
        if (inputBuffer.bytesAvailable > 0) { 
          onCompleteData(null); 
        }      
      } 
+0

Tout d'abord, je vous remercie d'avoir pris le temps de commenter et d'expliquer. C'est utile, surtout en ce qui concerne les tampons. Je devrais dire que le protocole que j'utilise est HTTP, donc je suppose que la longueur du contenu indique la taille de la réponse.Je ne suis pas sûr de savoir comment cela change (ou s'il est même utilisé) puisque la connexion ne se ferme jamais; peut-être qu'ils envoient des en-têtes HTTP à nouveau ou peut-être qu'ils ne le font pas. Je ne suis pas sûr de la différence entre socket buffer et URLStream, et je n'utiliserai pas un événement 'complete data', n'est-ce pas? Puisque la longue interrogation ne se termine jamais vraiment –

+0

La fonction CompleteData est un abus de langage ici. Cela ne signifie pas que le transfert de données est terminé. Le serveur envoie toujours des données, une fois les données copiées dans le tampon interne, le traitement des données est délégué à la fonction onCompleteData. Le serveur continue d'envoyer les données et onCompleteData traite les données. Pour répondre à votre question, Content-length définit la longueur des données brutes, bytesTotal dans votre cas. Si les données sont tronquées, vous ne saurez jamais quand un objet JSON est terminé. Si vous relayez sur le transfert HTTP, utilisez l'en-tête personnalisé qui indique la longueur JSON et extrayez les données en fonction de cette longueur. – prem

Questions connexes