如何完全实现消息轮询的服务器发送事件
How to fully implement server-sent events for message polling
我正在尝试使用 API.
与服务器通信
为了方便起见,我编写了一个脚本,该脚本将使用 php 脚本与 API 通信。
我的目标是每秒查询 API 以查看他们的队列中是否有新消息。
有人建议我使用 server-sent events 方法,让服务器仅在有新内容时才向客户端发送响应。
这是我的 php 脚本
<?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;
}
}
?>
当用户访问我的页面时,这是我 运行
<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>
我上面的代码不工作。
我的控制台中没有任何内容。但是这个错误 Firefox can't establish a connection to the server at /icws/poll.php
我怎样才能让它工作?
PHP 脚本实现的方式是否正确?
浏览器请求事件源 php 文件时的状态代码是什么?尝试使用 firebug 以确保它不是 404。
还有关于 php 代码。
根据您在问题中包含的 Mozilla 来源。
来自服务器的正确响应应命名并以换行符分隔
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: userconnect
data: {"username": "bobby", "time": "02:33:48"}
event: usermessage
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}
为了解决这个问题,我像这样添加了一个监听器事件
var evtSource = new EventSource("poll.php");
evtSource.addEventListener("ping", function(e) {
var obj = JSON.parse(e.data);
processMessages(obj);
}, false);
然后我像这样写了 processMessages
函数
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;
}
});
});
}
我的 PHP 代码如下所示
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);
}
PHP 中需要指出的几件事。重要的是在每行之后有 \n
并且在最后还有一个。同样重要的是寻找关键字 ping
,它位于我的 PHP 代码和我的 javascript 代码的侦听器事件中。如果你改变它,你必须改变它在 2 个地方。
我希望这对某人有所帮助:)
我正在尝试使用 API.
与服务器通信为了方便起见,我编写了一个脚本,该脚本将使用 php 脚本与 API 通信。
我的目标是每秒查询 API 以查看他们的队列中是否有新消息。
有人建议我使用 server-sent events 方法,让服务器仅在有新内容时才向客户端发送响应。
这是我的 php 脚本
<?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;
}
}
?>
当用户访问我的页面时,这是我 运行
<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>
我上面的代码不工作。
我的控制台中没有任何内容。但是这个错误 Firefox can't establish a connection to the server at /icws/poll.php
我怎样才能让它工作? PHP 脚本实现的方式是否正确?
浏览器请求事件源 php 文件时的状态代码是什么?尝试使用 firebug 以确保它不是 404。
还有关于 php 代码。
根据您在问题中包含的 Mozilla 来源。 来自服务器的正确响应应命名并以换行符分隔
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: userconnect
data: {"username": "bobby", "time": "02:33:48"}
event: usermessage
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}
为了解决这个问题,我像这样添加了一个监听器事件
var evtSource = new EventSource("poll.php");
evtSource.addEventListener("ping", function(e) {
var obj = JSON.parse(e.data);
processMessages(obj);
}, false);
然后我像这样写了 processMessages
函数
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;
}
});
});
}
我的 PHP 代码如下所示
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);
}
PHP 中需要指出的几件事。重要的是在每行之后有 \n
并且在最后还有一个。同样重要的是寻找关键字 ping
,它位于我的 PHP 代码和我的 javascript 代码的侦听器事件中。如果你改变它,你必须改变它在 2 个地方。
我希望这对某人有所帮助:)