How to fully implement server-sent events for message polling

拈花ヽ惹草 提交于 2019-12-10 16:35:40

问题


I am trying to communicate with a server using an API.

to make it easier I wrote a script that will communicate the API using a php script.

My goal is to make a query to the API every second to see if there is new message in their queue.

I was advised to use server-sent events method and have the server send a respond to the client only when it has something new.

Here is my php script

<?php

    // Register autoloader function
    spl_autoload_register('apiAutoloader');
    header("Content-Type: text/event-stream\n\n");

    $config = array('host' => 'server:IP',              //REQUIRED - Server Name
                    'port' => 8018,                     //REQUIRED - Server Port
                    'userID' => 'user',                 //REQUIRED - UserID to login with
                    'password' => '123456',             //REQUIRED - password for the UserID to login with
                    );

    try {

        //create a new instance of icws
        $icws = new API\ICWS($config); 

        //create a new session
        $icws->createSession(true);     

        while(1){

            $result = $icws->processMessage();
            echo json_encode($result);  

            ob_flush();
            flush();
            sleep(1);

        }

    } catch(Exception $e){
        echo $e->getMessage();
    }

    function apiAutoloader($className)
    {
        $className = ltrim($className, '\\');
        $fileName  = '';
        $namespace = '';

        if ($lastNsPos = strripos($className, '\\')) 
        {
            $namespace = substr($className, 0, $lastNsPos);
            $className = substr($className, $lastNsPos + 1);
            $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
        }

        $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

        $toLoad = dirname(__FILE__).'/'.$fileName;

        if (is_file($toLoad) === true)
        {
            include $toLoad;
        }
    }
?>

When a user visit my page this is the code the I run

<script>

    $(function(){

        function isset(a, b){

            if(typeof a !== "undefined" && a){
                return a
            }

            return b;
        }


        var evtSource = new EventSource("poll.php");

        evtSource.onmessage = function(e) {

            $.each(e.data.calls, function(i, item){

                $.each(item, function(z, c){

                    var interactionId = isset(c.interactionId, 0);
                    var Eic_CallDirection = isset(c.Eic_CallDirection, '');
                    var Eic_State = isset(c.Eic_State, '');
                    var AccoRDI_mid = isset(c.AccoRDI_mid, '');
                    var Eic_RemoteAddress = isset(c.Eic_RemoteAddress, '');

                    if(Eic_State == '' || Eic_CallDirection == ''){
                        return;
                    }

                    //incoming call that is not answered
                    if( Eic_CallDirection == 'I' && Eic_State == 'A'){
                        console.log('Incomming Call From ' + Eic_RemoteAddress + ' MID: ' + AccoRDI_mid );
                        return;
                    }

                    //on hold
                    if( Eic_State == 'H'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on hold' );
                        return;
                    }

                    //voicemail
                    if( Eic_State == 'M'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on leaving a voicemail' );
                        return;
                    }

                    //connected call
                    if(Eic_State == 'C'){
                        console.log('Live Call With ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'O'){
                        console.log('Dialling ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'R'){
                        console.log('Outbound call is rining and waiting for answer ' );
                        return;
                    }

                    //Call Disconnected
                    if(Eic_State == 'I' || Eic_State == 'E' ){
                        console.log('Hungup with ' + Eic_RemoteAddress );
                        return;
                    }

                });
            });
        }
    });
</script>

my code above is not working.

I don't get anything in my console. but this error Firefox can't establish a connection to the server at /icws/poll.php

How can I get it to work? Is the way I implemented by PHP script correct?


回答1:


What is the status code on the browser request for you event source php file ? Try to use firebug to make sure its not 404.

Also regarding php code.

According to Mozilla source you included in your question. Proper response from server should be named and separated by newlines

header("Content-Type: text/event-stream\n\n");     
while (1) {     
  echo "event: ping\n"; //event name
  echo 'data: '.json(); //event data
  Echo "\n\n"; //required  

  ob_flush(); flush(); sleep(1);    
 }

Event example

event: userconnect
data: {"username": "bobby", "time": "02:33:48"} 

event: usermessage
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."} 



回答2:


To solve this issue I added a listener event like so

        var evtSource = new EventSource("poll.php");

        evtSource.addEventListener("ping", function(e) {

          var obj = JSON.parse(e.data);
          processMessages(obj);

        }, false);

and I wrote my processMessages function like so

        function processMessages(obj) {

            $.each(obj.calls, function(i, item){

                $.each(item, function(z, c){

                    var interactionId = isset(c.interactionId, 0);
                    var Eic_CallDirection = isset(c.Eic_CallDirection, '');
                    var Eic_State = isset(c.Eic_State, '');
                    var mid = isset(c.mid, '');
                    var account_id = isset(c.account_id, '');
                    var Eic_RemoteAddress = isset(c.Eic_RemoteAddress, '');

                    if(Eic_State == '' || Eic_CallDirection == ''){
                        return;
                    }

                    //incoming call that is not answered
                    if( Eic_CallDirection == 'I' && Eic_State == 'A'){
                    var msg = '';
                        if(mid != ''){
                            msg = ' MID: ' + mid;
                        }

                        if(account_id != ''){
                            msg = ' Account ID: ' + account_id;
                        }
                        console.log('Incomming Call From ' + Eic_RemoteAddress + msg );
                        return;
                    }

                    //on hold
                    if( Eic_State == 'H'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on hold' );
                        return;
                    }

                    //voicemail
                    if( Eic_State == 'M'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on leaving a voicemail' );
                        return;
                    }

                    //connected call
                    if(Eic_State == 'C'){
                        console.log('Live Call With ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'O' && Eic_CallDirection = 'O'){
                        console.log('Dialling ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'R'){
                        console.log('Outbound call is rining and waiting for answer ' );
                        return;
                    }

                    //Call Disconnected
                    if(Eic_State == 'I' || Eic_State == 'E' ){
                        console.log('Hungup with ' + Eic_RemoteAddress );
                        return;
                    }

                });
            });
        }

and my PHP code looks like this

    while(1){

        $result = array('test' => 'This is a test records');
        echo 'event: ping' . "\n";
        echo 'data: ' . json_encode($result) . "\n";    
        echo "\n"; //required  

        ob_flush(); flush(); sleep(1);   

    }

Few things to point out in the PHP. It is IMPORTANT to have \nafter each line and one more at the very end. also it is important to look for the keyword ping which is located in my PHP code and in the listener event in my javascript code. if you change it you must change it in 2 places.

I hope this helps someone :)



来源:https://stackoverflow.com/questions/30279887/how-to-fully-implement-server-sent-events-for-message-polling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!