是否可以让PHP脚本通过websockets将数据发送到Node.js服务器?
我正在计划一个副项目,该项目将使PHP脚本在后台运行,并且最终用户将使用的前端应用程序将在Node.js中。 仅在 Node 中会有一些 socket.io 交互.js但我希望能够将数据从 PHP 脚本推送到 socket.io。
我也在研究这个问题。我的实现与其他实现略有不同。大多数人使用 php & curl + nodejs & express & socketio
我按以下方式完成:
- PHP 和 NodeJS 中的 memcache (共享 userid 和 cookie)(您也可以使用 Redis)
- 一个自定义 PHP 类,用于通过 websocket 向 localhost 发送请求,nodejs 服务器在其中广播到用户房间(来自同一用户的所有会话)。
这是我用来从 php 到 socketio 进行通信的类(只将数据发送到 nodejs,而不是绕过的方式!
当我连接到 socket.io 时,我的脚本会读取我的php cookie并将其发送到节点服务器,在那里它访问memcache json会话并识别用户,将他加入一个房间。
下面是一个 php json 序列化的 memcached 会话处理程序类。它类似于我使用的那个。
要在 php 中发出请求 --> socket.io 我执行以下操作:
$s = new SocketIO('127.0.0.1', 8088);
$adata = "On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain.";
$msg = json_encode(array('event'=> 'passdata','data'=> $adata, 'to'=> 1));
$tr = 0;
$fl = 0;
for ($i = 0 ; $i < 1000; $i++) {
$s->send( 'broadcast', $msg ) ? $tr++ : $fl++;
}
echo "HIT : " . $tr . PHP_EOL;
echo "MISS: " . $fl;
当来自本地主机的 (socket.io) 请求转到服务器时,我运行以下代码:
var is_local = (this_ip === '127.0.0.1' ? true : false);
socket.on('broadcast', function(data) {
if (data.length === 0 ) return;
if (is_local && typeof data === 'string') {
try {
var j = JSON.parse(data);
} catch (e) {
console.log("invalid json @ broadcast".red);
return false;
}
if (!j.hasOwnProperty('to') && !j.hasOwnProperty('event')) return false;
io.to(j.to).emit(j.event, j.data);
console.log('brc'.blue + ' to: ' + j.to + ' evt: ' + j.event);
/** @todo remove disconnect & try to create permanent connection */
socket.disconnect();
} else { console.log('brc ' + 'error'.red ); }
});
如果我想将数据从节点传递到 php,我只需在我的 nodejs 服务器上执行 php 代码。喜欢这个:
socket.on('php', function(func, data, callback) {
/* some functions */
if (check_usr(session) === false) return;
console.log('php'.green + ' act:' + func);
var cmd = 'php -r '$_COOKIE["MONSTER"]="' + session + '"; require("' + __dirname + '/' + php_[func].exec + '");'';
console.log(cmd);
cp.exec(cmd ,
function(err, stdout, stderr) {
if (err == null) {
console.log(typeof callback);
console.log(JSON.parse(callback));
if (callback != null) callback(stdout);
console.log(stdout);
//socket.emit('php', {uid: uid, o: stdout});
console.log('emitted');
} else {
console.log('err '.red + stdout + ' ' + stderr);
}
});
});
答案是肯定的,但确切的实施取决于您的环境/要求。
这是我从最近的一个项目中破解的一个例子:它发送一条消息,然后等待响应以 chr(10) ("") 结尾。必须在 0.5 秒内收到该响应,否则将假定失败(请参阅定时循环)。您可以根据需要摆弄这些位。
注意:$ip和$port需要传入。
$retval = false; // final return value will conatin something if it all works
$socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false || !is_resource($socket)) {
$socket = false;
$this->lastErrorNum = socket_last_error();
$this->lastErrorMsg = 'Unable to create socket: ' . socket_strerror(socket_last_error());
} elseif (!@socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to set options on socket: ' . socket_strerror($this->lastErrorNum);
@socket_clear_error ( $socket );
} elseif (!@socket_connect($socket, $ip, $port)) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to connect socket: ' . socket_strerror($this->lastErrorNum);
@socket_clear_error ( $socket );
} else {
// Socket connected - send message
if (!@socket_write($socket, $message, strlen($message))) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to write to socket: ' . socket_strerror($this->lastErrorNum);
@socket_clear_error ( $socket );
} else {
// Read a response
$receiveStartTime = microtime(true);
$response = '';
socket_set_nonblock ($socket);
while(microtime(true) - $receiveStartTime < 0.5) {
$n = @socket_recv($socket, $dataIn, 1024, 0); // Assume max return value is 1024 bytes.
if ($n) {
$response .= $dataIn;
}
if (strpos($dataIn, "n") !== false) {
@socket_clear_error ( $socket );
$response = str_replace("n", '', $response);
break;
}
}
if (socket_last_error($socket) > 0) {
$this->lastErrorNum = socket_last_error($socket);
$this->lastErrorMsg = 'Unable to read from socket: ' . socket_strerror($this->lastErrorNum);
@socket_clear_error ( $socket );
} else {
$retval = $response;
}
}
@socket_close($socket);
}