Visualizzazione risultati 1 fino 9 di 9

Discussione: Problema refresh chat e utenti online con long polling

  1. #1
    sneh non è connesso Neofita
    Data registrazione
    22-03-2015
    Messaggi
    8

    Predefinito Problema refresh chat e utenti online con long polling

    Sto cercando di creare una sorta di chattina in long polling, però il CloadFlare un pò mi da problemi per tutte le chiamate che fa: per tanto vi vorrei chiedere se i miei codici sono da ottimizzare, vi passo le due funzioni dove faccio le richieste più pesanti: Online() (aggiorna gli utenti online) e Euphoria() (aggiorna la chat con un nuovo messaggio)

    CLIENT:
    script client che fa richieste longPolling json al file requests.php:
    ###PS: ho oscurato le funzioni cun cui creo gli elementi nel doom, perché futili al problema
    Codice PHP:
    <script>
    function Online(content){
    var data = null;
    if(content == null) data = {<?=REQUEST_TYPE?>:'getPollOnline'};
    else data = {<?=REQUEST_TYPE?>:'getPollOnline','content' : content};
    $.ajax({
    url:"requests",
    method:"post",
    dataType:"json",
    data:data,
    success:function(data){

    makeOnlineList(data["users"]); //aggiorna gli utenti online
    online_update++;
    Online(data);
    },
    error:function(){
    return;
    }
    });
    }
    function Euphoria(id){
    var data = null;
    if(id == null) data = {<?=REQUEST_TYPE?>:'getPoll'};
    else data = {<?=REQUEST_TYPE?>:'getPoll','id' : id};
    $.ajax({
    url:"requests",
    method:"post",
    dataType:"json",
    data:data,
    success:function(data){
    addNewMessage(data,false); //aggiunge il nuovo messaggio ala chat
    last_update++;
    Euphoria(data.id);
    },
    error:function(){
    return;
    }
    });
    }


    //variabili per accendere o no delle funzioni nel setInterval sotto
    var current_update,current_online_update = 0;
    var last_update,online_update = 0;
    jQuery(function($) {

    //EuphoriaAll(null,true); //questa funzione è per mostrare tutti i messaggi all'inizio però non è completa
    Euphoria(); //questa funzione se comprendo che il database è cambiato, aggiorno la chat
    Online(); //stessa roba per la chat ma per gli utenti online

    //questo setInterval gira ogni minuto e riaccende una data funzione nel caso il server non fosse più attivo
    setInterval(function(){
    if(last_update > current_update && $.active > 0){
    current = last_update;
    Euphoria();
    //Online();
    }
    else if(online_update > current_online_update && $.active > 0){
    // Euphoria();
    Online();
    }
    },60000);

    //qua mostro solo se uno sta digitando o no
    //al keydown aziona, nel keyup se si sta digitando toglie la digitazione dopo 2s, al blur leva la digitazione
    var on_digits = false;
    $("#message").keydown(function(){
    toggleDigits("visible");
    on_digits = true;
    }).keyup(function(){
    if(on_digits){
    setTimeout(function(){
    toggleDigits("none");
    },2000);

    }
    }).blur(function(){
    toggleDigits("none");
    on_digits = false;
    });


    //sulla testarea invio i dati al form dopo aver premuto enter
    $("#message").keydown(function(e){
    if(e.keyCode === 13){
    if(e.shiftKey) return;
    else {
    $("form[data='chat']").submit();
    }
    }
    });
    $("form[data='chat']").submit(function(e){
    e.preventDefault();
    var data = $(this).serialize();
    data+="&<?=REQUEST_TYPE?>=putMessage";
    $.post("requests",data,function(e){
    });
    $("#message").val("").get(0).setSelectionRange(0,0);
    setTimeout(function () { $("#message").val(null); }, 20);
    });

    });
    </script>
    File requests delle due richieste:

    Codice PHP:
    case "getPollOnline": #aggiorna gli online
    header("Content-Type: application/json");
    set_time_limit(0);
    while (
    true) {
    $last_request_content = isset($_REQUEST['content']) ? (object)$_REQUEST['content'] : null;
    clearstatcache();
    $last_list = ONLINE::getList(time());
    //last_list è un oggetto vario contenente anche un array "hash" e calcolo la diversità con quello
    if ($last_request_content == null || $last_list["hash"] !== $last_request_content->hash ) {
    #CONF::json(...) == json_encode(...)
    echo CONF::json($last_list); #qui cedo a client il json della mia lsta
    break;
    } else {
    sleep(1);
    continue;
    }
    }
    break;
    case
    "getPoll": #aggiorna la chat con un nuovo messaggio
    header("Content-Type: application/json");
    set_time_limit(0);
    while (
    true) {
    $last_request_id = isset($_REQUEST['id']) ? (int)$_REQUEST['id'] : null;
    clearstatcache();
    $last_message = CHAT::getLast();
    if (
    $last_request_id == null || $last_message->id > $last_request_id) {
    echo
    CONF::json($last_message);
    break;
    } else {
    sleep(1);
    continue;
    }
    }
    break;
    Ultima modifica di sneh : 24-03-2018 alle ore 19.42.06

  2. #2
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Il codice JavaScript è un po' lungo per esaminarlo tutto su due piedi.
    Quello che ho notato a colpo d'occhio è questo frammento:
    Codice:
    function Online(content){
      ...
      $.ajax({
        ...
        success: function(data) {
            ...
            Online(data);
        },
        ...
      });
    Ovvero il fatto che la funzioneOnline (così come Euphoria) chiama ricorsivamente ed immediatamente se stessa ogni volta che la chiamata Ajax ha successo.
    In pratica la rete è costantemente occupata da chiamate Ajax, appena ne termina una con successo ne parte un'altra, in questo modo tieni aggiornati tutti i client con il minor ritardo possibile.
    Non credo che per una chat avere dei tempi di risposta così brevi sia necessario, e se questo ti crea problemi con la quantità di richieste suggerirei di inserire una pausa tra un aggiornamento e l'altro, ad esempio con
    Codice:
    setTimeout(Online, 500);

  3. #3
    sneh non è connesso Neofita
    Data registrazione
    22-03-2015
    Messaggi
    8

    Predefinito

    Una cosa brutta è che dopo tot di tempo se il server non risponde più, non ricarica più le funzioni euphoria e online
    per tanto ho scritto questi codici :
    Codice PHP:
    setInterval(function(){
    if(
    last_update > current_update && $.active > 0){
    current = last_update;
    Euphoria();
    Online();
    }
    else if(
    online_update > current_online_update && $.active > 0){
    Euphoria();
    Online();
    }
    },
    60000);
    in caso di assenza dela risposta del server, dopo un minuto le riaccendo se non ci sono poling, questa cosa del $.active in realtà non credo di averla pensata bene

    infatti capita che non ricarichi le cose al cambiamento del database che leggo nella parte php

  4. #4
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Ho guardato anche il codice PHP. Ci sono alcuni problemi di fondo:
    Codice PHP:
    switch (...) {
    case
    "getPollOnline":
    set_time_limit(0);
    ...
    while (
    true) {
    ...
    if (...)
    break
    else
    continue
    }
    break;
    }
    Dubito che set_time_limit(0) abbia effetto in un server condiviso: se potesse avere effetto e tutti lo usassero, il server collasserebbe.

    Questo automaticamente rende inutile l'uso del while(true) e di questa struttura del codice, e spiega perché dopo un po' il server non risponde più: raggiunge il timeout.

    Capisco che quei while (true) abbiano lo scopo di mettere in attesa server e client finché i dati aggiornati sono disponibili, ma con PHP su un web server questa non è una strada percorribile.
    Il metodo più pratico è quello descritto in How do I implement basic “Long Polling”?, il "problema" è che non è più un vero long polling.

    Anche nella discussione su Stack Overflow suggeriscono di usare strumenti diversi da PHP per lo stesso motivo.

  5. #5
    sneh non è connesso Neofita
    Data registrazione
    22-03-2015
    Messaggi
    8

    Predefinito

    Sta di fatto che io voglio usare Altervista, anche io per una chat di messagistica userei websockets in nodejs o rachet per dirci, ma io voglio fare questa cosa qui su Altervista e se col php non potrò far molto, mi baserò su degli eventi specifici in javascript per ricaricare i messaggi richiedendo comunque delle richieste ajax al server. Altro non so, se si può fare qua di messaggistico su Altervista , oltre ai metodi quelli che sto usando, non ne conosco.

    Secondo il tuo consiglio ho levato lo set_time_limit(0)
    Ultima modifica di sneh : 26-03-2018 alle ore 12.42.46

  6. #6
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Messaggistica su AlterVista con PHP + JavaScript si può ottenere, ma non con il (vero) long polling.
    Con il polling "semplice" non dovresti avere problemi.

  7. #7
    sneh non è connesso Neofita
    Data registrazione
    22-03-2015
    Messaggi
    8

    Predefinito

    long polling semplice? intendi leggere ogni tot di tempo il server?

  8. #8
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Sì, il classico, orribile, inefficiente polling
    Che io sappia, in ambito web è l'unica vera alternativa.

  9. #9
    sneh non è connesso Neofita
    Data registrazione
    22-03-2015
    Messaggi
    8

    Predefinito

    Che cosa brutta

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •