Comment puis-je implémenter le «Long Polling» de base?


776

Je peux trouver beaucoup d'informations sur le fonctionnement de l'interrogation longue (par exemple, ceci et cela ), mais pas d' exemples simples sur la façon de l'implémenter dans le code.

Tout ce que je peux trouver, c'est cometd , qui repose sur le framework Dojo JS, et un système de serveur assez complexe.

Fondamentalement, comment pourrais-je utiliser Apache pour répondre aux demandes et comment pourrais-je écrire un script simple (par exemple, en PHP) qui "interrogerait longuement" le serveur pour les nouveaux messages?

L'exemple ne doit pas être évolutif, sécurisé ou complet, il doit juste fonctionner!

Réponses:


512

C'est plus simple que je ne le pensais au départ. Fondamentalement, vous avez une page qui ne fait rien, jusqu'à ce que les données que vous souhaitez envoyer soient disponibles (par exemple, un nouveau message arrive).

Voici un exemple vraiment basique, qui envoie une chaîne simple au bout de 2 à 10 secondes. 1 chance sur 3 de retourner une erreur 404 (pour montrer la gestion des erreurs dans l'exemple Javascript à venir)

msgsrv.php

<?php
if(rand(1,3) == 1){
    /* Fake an error */
    header("HTTP/1.0 404 Not Found");
    die();
}

/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>

Remarque: Avec un site réel, l'exécuter sur un serveur Web ordinaire comme Apache bloquera rapidement tous les «threads de travail» et le laissera incapable de répondre à d'autres demandes. Il existe des moyens de contourner cela, mais il est recommandé d'écrire un "serveur à interrogation longue" dans quelque chose comme Python tordu , qui ne repose pas sur un thread par demande. cometD est populaire (disponible en plusieurs langues), et Tornado est un nouveau framework spécialement conçu pour ces tâches (il a été conçu pour le code de polling long de FriendFeed) ... mais à titre d'exemple simple, Apache est plus que suffisant ! Ce script pourrait facilement être écrit dans n'importe quelle langue (j'ai choisi Apache / PHP car ils sont très courants et je les ai exécutés localement)

Ensuite, en Javascript, vous demandez le fichier ci-dessus ( msg_srv.php) et attendez une réponse. Lorsque vous en obtenez un, vous agissez sur les données. Ensuite, vous demandez le fichier et attendez à nouveau, agissez sur les données (et répétez)

Ce qui suit est un exemple d'une telle page. Lorsque la page est chargée, elle envoie la demande initiale pour le msgsrv.phpfichier. Si elle réussit, nous ajoutons le message à la #messagesdiv, puis après 1 seconde nous appelons à nouveau la fonction waitForMsg, ce qui déclenche l'attente.

La 1 seconde setTimeout()est un limiteur de débit vraiment basique, cela fonctionne très bien sans cela, mais s'il revient msgsrv.php toujours instantanément (avec une erreur de syntaxe, par exemple) - vous inondez le navigateur et il peut rapidement geler. Il serait préférable de vérifier si le fichier contient une réponse JSON valide et / ou de conserver un total cumulé de requêtes par minute / seconde, et de faire une pause appropriée.

Si la page fait une erreur, il ajoute l'erreur à la #messagesdiv, attend 15 secondes puis réessaye (identique à la façon dont nous attendons 1 seconde après chaque message)

La bonne chose à propos de cette approche est qu'elle est très résistante. Si la connexion Internet du client meurt, elle expirera, puis essayez de vous reconnecter - cela est inhérent à la durée de l'interrogation, aucune gestion d'erreur complexe n'est requise

Quoi qu'il en soit, le long_poller.htmcode, en utilisant le framework jQuery:

<html>
<head>
    <title>BargePoller</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>

    <style type="text/css" media="screen">
      body{ background:#000;color:#fff;font-size:.9em; }
      .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
      .old{ background-color:#246499;}
      .new{ background-color:#3B9957;}
    .error{ background-color:#992E36;}
    </style>

    <script type="text/javascript" charset="utf-8">
    function addmsg(type, msg){
        /* Simple helper to add a div.
        type is the name of a CSS class (old/new/error).
        msg is the contents of the div */
        $("#messages").append(
            "<div class='msg "+ type +"'>"+ msg +"</div>"
        );
    }

    function waitForMsg(){
        /* This requests the url "msgsrv.php"
        When it complete (or errors)*/
        $.ajax({
            type: "GET",
            url: "msgsrv.php",

            async: true, /* If set to non-async, browser shows page as "Loading.."*/
            cache: false,
            timeout:50000, /* Timeout in ms */

            success: function(data){ /* called when request to barge.php completes */
                addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
                setTimeout(
                    waitForMsg, /* Request next message */
                    1000 /* ..after 1 seconds */
                );
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
                addmsg("error", textStatus + " (" + errorThrown + ")");
                setTimeout(
                    waitForMsg, /* Try again after.. */
                    15000); /* milliseconds (15seconds) */
            }
        });
    };

    $(document).ready(function(){
        waitForMsg(); /* Start the inital request */
    });
    </script>
</head>
<body>
    <div id="messages">
        <div class="msg old">
            BargePoll message requester!
        </div>
    </div>
</body>
</html>

7
Certains messages n'ont-ils pas pu passer à travers cette idée? Dans ce délai d'une seconde, disons que 1000 messages de discussion ont été envoyés, comment le serveur pourrait-il envoyer les 1000 messages spécifiquement à ce client?
DevDevDev

15
Probablement. Ceci est un exemple très simplifié, pour illustrer le concept. Pour faire mieux, vous auriez besoin d'un code côté serveur plus élaboré, où il stockerait ces 1000 messages pour ce client spécifique et les enverrait en un seul morceau. Vous pouvez également réduire le délai d'attente waitForMsg en toute sécurité
dbr

21
nodejs est une autre excellente solution côté serveur pour les longues requêtes d'interrogation, avec l'avantage supplémentaire (par rapport à Twisted) que vous pouvez également écrire du code serveur en Javascript.
Husky

8
Il s'agit simplement d'une simple connexion AJAX récurrente au serveur avec un intervalle de 1 seconde. Cela n'a rien à voir avec le "long scrutin". L'interrogation longue doit maintenir la connexion active, tant que le délai d'expiration du client est atteint.
Deele

6
la question est de savoir à quoi sert un vrai script PHP sleep(rand(2,10));? pour ne rien faire, interroger la base de données tous les 100 milisecs? quand décide-t-il de mourir?
Luis Siquot

41

J'ai un exemple de chat vraiment simple dans le cadre de slosh .

Edit : (puisque tout le monde colle son code ici)

Il s'agit du chat multi-utilisateurs complet basé sur JSON utilisant une interrogation longue et slosh . Ceci est une démonstration de la façon de faire les appels, veuillez donc ignorer les problèmes XSS. Personne ne devrait déployer cela sans le désinfecter au préalable.

Notez que le client a toujours une connexion au serveur, et dès que quelqu'un envoie un message, tout le monde devrait le voir à peu près instantanément.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2008 Dustin Sallings <dustin+html@spy.net> -->
<html lang="en">
  <head>
    <title>slosh chat</title>
    <script type="text/javascript"
      src="http://code.jquery.com/jquery-latest.js"></script>
    <link title="Default" rel="stylesheet" media="screen" href="style.css" />
  </head>

  <body>
    <h1>Welcome to Slosh Chat</h1>

    <div id="messages">
      <div>
        <span class="from">First!:</span>
        <span class="msg">Welcome to chat. Please don't hurt each other.</span>
      </div>
    </div>

    <form method="post" action="#">
      <div>Nick: <input id='from' type="text" name="from"/></div>
      <div>Message:</div>
      <div><textarea id='msg' name="msg"></textarea></div>
      <div><input type="submit" value="Say it" id="submit"/></div>
    </form>

    <script type="text/javascript">
      function gotData(json, st) {
        var msgs=$('#messages');
        $.each(json.res, function(idx, p) {
          var from = p.from[0]
          var msg = p.msg[0]
          msgs.append("<div><span class='from'>" + from + ":</span>" +
            " <span class='msg'>" + msg + "</span></div>");
        });
        // The jQuery wrapped msgs above does not work here.
        var msgs=document.getElementById("messages");
        msgs.scrollTop = msgs.scrollHeight;
      }

      function getNewComments() {
        $.getJSON('/topics/chat.json', gotData);
      }

      $(document).ready(function() {
        $(document).ajaxStop(getNewComments);
        $("form").submit(function() {
          $.post('/topics/chat', $('form').serialize());
          return false;
        });
        getNewComments();
      });
    </script>
  </body>
</html>

1
Puis-je savoir comment cela est toujours connecté? Désolé si je demande quelque chose de stupide, mais je veux le savoir.
Rocky Singh

4
Il effectue un HTTP GET et le serveur bloque le GET jusqu'à ce qu'il y ait des données disponibles. Lorsque les données arrivent sur le serveur, le serveur renvoie les données au client, met en file d'attente tout ce qui pourrait arriver, puis le client se reconnecte et récupère les messages manquants, le cas échéant, sinon il se bloque à nouveau.
Dustin

4
Peut ne pas être évident au début, mais le fait est que le responsable de `` l'état toujours connecté '' est ajaxStop avec getNewCommentsrappel là-bas, donc il le déclenche à la fin de chaque demande ajax sans fin
baldrs

32

Tornado est conçu pour les longues interrogations et comprend une application de discussion très minimale (quelques centaines de lignes de Python) dans / examples / chatdemo , y compris le code du serveur et le code du client JS. Cela fonctionne comme ceci:

  • Les clients utilisent JS pour demander des mises à jour car (numéro du dernier message), le serveur URLHandler les reçoit et ajoute un rappel pour répondre au client dans une file d'attente.

  • Lorsque le serveur reçoit un nouveau message, l'événement onmessage se déclenche, parcourt les rappels et envoie les messages.

  • Le JS côté client reçoit le message, l'ajoute à la page, puis demande des mises à jour depuis ce nouvel ID de message.


25

Je pense que le client ressemble à une requête AJAX asynchrone normale, mais vous vous attendez à ce que cela prenne "longtemps" pour revenir.

Le serveur ressemble alors à ceci.

while (!hasNewData())
    usleep(50);

outputNewData();

Ainsi, la demande AJAX va au serveur, incluant probablement un horodatage de la dernière mise à jour afin que vous hasNewData()sachiez quelles données vous avez déjà. Le serveur se trouve alors dans une boucle en veille jusqu'à ce que de nouvelles données soient disponibles. Pendant tout ce temps, votre demande AJAX est toujours connectée, suspendue juste en attente de données. Enfin, lorsque de nouvelles données sont disponibles, le serveur les transmet à votre requête AJAX et ferme la connexion.


10
Il s'agit d'une attente occupée qui bloque votre thread actuel. Cela ne change pas du tout.
Wouter Lievens

10
Non, l'usure n'est pas une attente bien remplie. Et le but de "l'attente" est de bloquer votre fil pendant un certain temps. Il voulait probablement dire 50 millisecondes (usleep (50000)) cependant, pas 50 microsecondes! Mais de toute façon, avec une configuration Apache / PHP typique, existe-t-il une autre façon de procéder?
Matt

Eh bien, depuis le priciple, vous ne pouvez pas faire une fonction de blocage pour le message de chat sans attendre.
Tomáš Zato - Rétablir Monica

Super vraiment! J'ai construit une fonction récursive sur le serveur pour vérifier les nouvelles données. Mais quel est le meilleur produit pour utiliser efficacement les longs sondages? J'utilise Apache normal et le serveur ne répond pas lorsque j'ouvre plus de 4/5 onglets de navigateur :( Vous cherchez quelque chose à utiliser avec PHP
moderns

17

Voici quelques classes que j'utilise pour les longues interrogations en C #. Il existe essentiellement 6 classes (voir ci-dessous).

  1. Contrôleur : traite les actions requises pour créer une réponse valide (opérations db, etc.)
  2. Processeur : gère la communication asynchrone avec la page Web (elle-même)
  3. IAsynchProcessor : le service traite les instances qui implémentent cette interface
  4. Sevice : les processus demandent des objets qui implémentent IAsynchProcessor
  5. Requête : le wrapper IAsynchProcessor contenant votre réponse (objet)
  6. Réponse : contient des objets ou des champs personnalisés

2
D'accord ... alors POURQUOI cela a-t-il été rejeté? Ces classes sont en effet des exemples valables d'interrogation longue.
Prisonnier ZERO

La véritable interrogation longue n'est pas (simplement) la pratique d'augmenter l'intervalle dans lequel vous effectuez une interrogation normale (sur une ressource). Cela fait partie d'un schéma plus large ... qui est "quelque peu" sujet à interprétation ... mais seulement dans certains domaines de la mise en œuvre globale. Cela dit ... ces cours suivent ce modèle! Donc, si vous avez une raison de voter contre ... Je serais vraiment intéressé par la raison.
Prisonnier ZERO

Il a peut-être été rejeté, car il ne traite pas directement la question d'un simple exemple de code. Bien sûr, je ne l'ai pas voté, je ne peux que deviner.
Andrew

16

Ceci est un joli screencast de 5 minutes sur la façon de faire de longs sondages en utilisant PHP et jQuery: http://screenr.com/SNH

Le code est assez similaire à l'exemple de dbr ci-dessus.


3
Je pense que vous ne devriez voir cela que comme une introduction à l'interrogation longue car cette implémentation tuera à coup sûr votre serveur avec de nombreux utilisateurs simultanés.
Alfred

je suis juste en train d'apprendre tout cela ... à quel point est-ce fiable ou pas, avec quelques utilisateurs ... disons 10 bavarder en arrière?
somdow

12

Voici un exemple simple d'interrogation longue en PHP par Erik Dubbelboer utilisant l'en- Content-type: multipart/x-mixed-replacetête:

<?

header('Content-type: multipart/x-mixed-replace; boundary=endofsection');

// Keep in mind that the empty line is important to separate the headers
// from the content.
echo 'Content-type: text/plain

After 5 seconds this will go away and a cat will appear...
--endofsection
';
flush(); // Don't forget to flush the content to the browser.


sleep(5);


echo 'Content-type: image/jpg

';

$stream = fopen('cat.jpg', 'rb');
fpassthru($stream);
fclose($stream);

echo '
--endofsection
';

Et voici une démo:

http://dubbelboer.com/multipart.php


11

J'ai utilisé ce pour se familiariser avec la comète, j'ai également mis en place Comet en utilisant le serveur Java Glassfish et a trouvé beaucoup d'autres exemples en vous inscrivant à cometdaily.com



9

Voici une longue solution d'interrogation que j'ai développée pour Inform8 Web. Fondamentalement, vous remplacez la classe et implémentez la méthode loadData. Lorsque le loadData renvoie une valeur ou que l'opération expire, il imprime le résultat et retourne.

Si le traitement de votre script peut prendre plus de 30 secondes, vous devrez peut-être modifier l'appel set_time_limit () en quelque chose de plus long.

Licence Apache 2.0. Dernière version sur github https://github.com/ryanhend/Inform8/blob/master/Inform8-web/src/config/lib/Inform8/longpoll/LongPoller.php

Ryan

abstract class LongPoller {

  protected $sleepTime = 5;
  protected $timeoutTime = 30;

  function __construct() {
  }


  function setTimeout($timeout) {
    $this->timeoutTime = $timeout;
  }

  function setSleep($sleep) {
    $this->sleepTime = $sleepTime;
  }


  public function run() {
    $data = NULL;
    $timeout = 0;

    set_time_limit($this->timeoutTime + $this->sleepTime + 15);

    //Query database for data
    while($data == NULL && $timeout < $this->timeoutTime) {
      $data = $this->loadData();
      if($data == NULL){

        //No new orders, flush to notify php still alive
        flush();

        //Wait for new Messages
        sleep($this->sleepTime);
        $timeout += $this->sleepTime;
      }else{
        echo $data;
        flush();
      }
    }

  }


  protected abstract function loadData();

}

8

Merci pour le code, dbr . Juste une petite faute de frappe dans long_poller.htm autour de la ligne

1000 /* ..after 1 seconds */

Je pense que ça devrait être

"1000"); /* ..after 1 seconds */

pour que cela fonctionne.

Pour ceux qui sont intéressés, j'ai essayé un équivalent Django. Démarrez un nouveau projet Django, dites lp pour une longue interrogation:

django-admin.py startproject lp

Appelez l'application msgsrv pour le serveur de messages:

python manage.py startapp msgsrv

Ajoutez les lignes suivantes à settings.py pour avoir un répertoire de modèles :

import os.path
PROJECT_DIR = os.path.dirname(__file__)
TEMPLATE_DIRS = (
    os.path.join(PROJECT_DIR, 'templates'),
)

Définissez vos modèles d'URL dans urls.py comme tels:

from django.views.generic.simple import direct_to_template
from lp.msgsrv.views import retmsg

urlpatterns = patterns('',
    (r'^msgsrv\.php$', retmsg),
    (r'^long_poller\.htm$', direct_to_template, {'template': 'long_poller.htm'}),
)

Et msgsrv / views.py devrait ressembler à:

from random import randint
from time import sleep
from django.http import HttpResponse, HttpResponseNotFound

def retmsg(request):
    if randint(1,3) == 1:
        return HttpResponseNotFound('<h1>Page not found</h1>')
    else:
        sleep(randint(2,10))
        return HttpResponse('Hi! Have a random number: %s' % str(randint(1,10)))

Enfin, templates / long_poller.htm devrait être le même que ci-dessus avec une faute de frappe corrigée. J'espère que cela t'aides.


En fait, "15000"c'est l'erreur de syntaxe. setTimeout prend un entier comme deuxième paramètre.
Andrew Hedges

Cette réponse a besoin de travail. C'est l'aboutissement d'un ou plusieurs commentaires et d'une ou de plusieurs réponses distinctes.
Brian Webster

8

C'est l'un des scénarios pour lesquels PHP est un très mauvais choix. Comme mentionné précédemment, vous pouvez attacher très rapidement tous vos employés Apache en faisant quelque chose comme ça. PHP est conçu pour démarrer, exécuter, arrêter. Il n'est pas conçu pour démarrer, attendre ... exécuter, arrêter. Vous enlèverez votre serveur très rapidement et découvrirez que vous avez des problèmes de mise à l'échelle incroyables.

Cela dit, vous pouvez toujours le faire avec PHP et ne pas tuer votre serveur en utilisant le nginx HttpPushStreamModule: http://wiki.nginx.org/HttpPushStreamModule

Vous configurez nginx devant Apache (ou quoi que ce soit d'autre) et il se chargera de maintenir ouvertes les connexions simultanées. Vous répondez simplement avec une charge utile en envoyant des données à une adresse interne que vous pourriez faire avec un travail en arrière-plan ou en envoyant simplement les messages aux personnes qui attendaient chaque fois que les nouvelles demandes arrivaient. Cela empêche les processus PHP de rester ouverts pendant une longue interrogation.

Ceci n'est pas exclusif à PHP et peut être fait en utilisant nginx avec n'importe quel langage backend. La charge des connexions ouvertes simultanées est égale à Node.js, donc le plus grand avantage est qu'il vous permet de sortir de NEDING Node pour quelque chose comme ça.

Vous voyez beaucoup d'autres personnes mentionner d'autres bibliothèques de langues pour avoir effectué un long sondage et c'est pour une bonne raison. PHP n'est tout simplement pas bien conçu pour ce type de comportement naturellement.


Est-ce un problème Apache ou un problème PHP? Aurais-je des problèmes avec l'interrogation longue si mon code PHP s'exécutait directement sur nginx ou lighttpd?
David

C'est moins un problème PHP et plus une mauvaise utilisation de PHP. À chaque demande, PHP exécute le script à partir de zéro, en chargeant les bibliothèques selon les besoins, en exécutant son code puis en s'arrêtant pendant que le ramasse-miettes commence tout dans la demande. De nombreuses modifications ont été apportées à PHP au fil des ans pour minimiser l'impact comme les liaisons statiques tardives, le chargement paresseux, les caches de bytecode en mémoire pour supprimer les E / S de disque, etc. Le problème demeure que PHP est destiné à démarrer et à s'arrêter aussi rapidement que possible. Les langues qui se chargeront une fois / boot et ouvriront un thread pour la demande sont bien mieux adaptées aux longues interrogations.
brightball

Mais pour répondre à la question, oui, vous rencontriez le problème, que vous utilisiez Apache ou autre chose. C'est juste comment PHP fonctionne. Je devrais modifier cela pour dire que, si vous allez avoir une charge de trafic maximale connue, PHP ira bien. J'ai vu des systèmes embarqués utilisant PHP qui n'ont aucun problème car il n'y a que quelques connexions. Potentiellement sur un intranet d'entreprise, cela pourrait également être passable. Pour les applications destinées au public, vous allez absolument tuer vos serveurs à mesure que le trafic augmente.
brightball

4

Pourquoi ne pas envisager les sockets Web au lieu de longues interrogations? Ils sont très efficaces et faciles à installer. Cependant, ils ne sont pris en charge que dans les navigateurs modernes. Voici une référence rapide .


Je pense qu'une fois que les websockets seront implémentées partout (probablement pas pour les années à venir), elles seront la norme pour ce type d'application. Malheureusement pour l'instant, nous ne pouvons pas compter sur eux pour les applications de production.
Richard

3
@Richard Vous pouvez cependant utiliser quelque chose comme Socket.IO qui fournit des transports de secours automatiques, fournissant des fonctionnalités de type socket Web jusqu'à IE 6.
Brad

3

Le groupe WS-I a publié quelque chose appelé "Reliable Secure Profile" qui a une implémentation de Glass Fish et .NET qui interagit apparemment bien.

Avec un peu de chance, il existe également une implémentation Javascript .

Il existe également une implémentation Silverlight qui utilise HTTP Duplex. Vous pouvez connecter javascript à l' objet Silverlight pour obtenir des rappels lorsqu'un push se produit.

Il existe également des versions commerciales payantes .



2

Vous pouvez essayer icomet ( https://github.com/ideawu/icomet ), un serveur de comète C1000K C ++ construit avec libevent. icomet fournit également une bibliothèque JavaScript, il est facile à utiliser aussi simple que

var comet = new iComet({
    sign_url: 'http://' + app_host + '/sign?obj=' + obj,
    sub_url: 'http://' + icomet_host + '/sub',
    callback: function(msg){
        // on server push
        alert(msg.content);
    }
});

icomet prend en charge une large gamme de navigateurs et de systèmes d'exploitation, y compris Safari (iOS, Mac), IE (Windows), Firefox, Chrome, etc.


0

NodeJS le plus simple

const http = require('http');

const server = http.createServer((req, res) => {
  SomeVeryLongAction(res);
});

server.on('clientError', (err, socket) => {
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

server.listen(8000);

// the long running task - simplified to setTimeout here
// but can be async, wait from websocket service - whatever really
function SomeVeryLongAction(response) {
  setTimeout(response.end, 10000);
}

Scénario de production dans Express pour exmaple que vous obtiendriez responsedans le middleware. Faites-vous ce que vous devez faire, pouvez étendre toutes les méthodes d'interrogation longues pour mapper ou quelque chose (qui est visible pour les autres flux), et invoquer <Response> response.end()chaque fois que vous êtes prêt. Les connexions longues interrogées n'ont rien de spécial. Le reste est juste la façon dont vous structurez normalement votre application.

Si vous ne savez pas ce que je veux dire par délimitation, cela devrait vous donner une idée

const http = require('http');
var responsesArray = [];

const server = http.createServer((req, res) => {
  // not dealing with connection
  // put it on stack (array in this case)
  responsesArray.push(res);
  // end this is where normal api flow ends
});

server.on('clientError', (err, socket) => {
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

// and eventually when we are ready to resolve
// that if is there just to ensure you actually 
// called endpoint before the timeout kicks in
function SomeVeryLongAction() {
  if ( responsesArray.length ) {
    let localResponse = responsesArray.shift();
    localResponse.end();
  }
}

// simulate some action out of endpoint flow
setTimeout(SomeVeryLongAction, 10000);
server.listen(8000);

Comme vous le voyez, vous pouvez vraiment répondre à toutes les connexions, un, faites ce que vous voulez. Il y en a idpour chaque demande, vous devriez donc pouvoir utiliser la carte et accéder à des appels spécifiques hors api.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.