问题
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 \n
after 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