php - PHP curl 向 Node.js 发送消息不返回结果
问题描述
我想将 websockets 实现到复杂的 web 系统以正确同步数据。这个想法是所有客户端都可以进行 ajax 调用,php 处理这些调用,可以编辑数据库上的数据,并且成功后 php-backend 将一些数据发送到 websocket-server。然后,该 websocket 服务器将数据发送到所有可能对数据感兴趣的订阅客户端。
到目前为止,客户端可以订阅 websocket 服务器(socket.io),但我不知道如何让 php 向 websocket 服务器发送消息。
到目前为止,我的 websocket 服务器看起来像这样:
const fs = require('fs');
const credentials = {
key: fs.readFileSync('C:/xampp/apache/conf/ssl.key/server.key'),
cert: fs.readFileSync('C:/xampp/apache/conf/ssl.crt/server.crt')
};
const app = require('express')();
// var server = require('https').Server(app);
let server = require('https').createServer(credentials, app);
let io = require('socket.io')(server);
server.listen(3000);
io.sockets.on('connection', function(socket){
console.log("connected");
socket.emit('test', { hello: 'world' });
socket.on('some other event', function (data) {
console.log(data);
});
socket.on('subscribe', function(room) {
console.log('joining room', room);
socket.join(room);
});
socket.on('unsubscribe', function(room) {
console.log('leaving room', room);
socket.leave(room);
});
socket.on('send', function(data) {
console.log('sending message');
io.sockets.in(data.room).emit('message', data);
});
});
我的 php 调用如下所示:
require_once __DIR__.'/../vendor/autoload.php';
$dbHandler = \services\DBHandling::getInstance();
$data = [
"subscribe" => "room3",
"message" => "evacuate nuclear reactor block B !"
];
$data_string = json_encode($data);
$curl = curl_init("http://localhost");
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER,['Content-Type: application/json',
'Content-Length: ' . strlen($data_string)
]);
curl_setopt($curl,CURLOPT_PORT, 3000);
curl_setopt($curl,CURLOPT_POST,true);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl,CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl,CURLOPT_POSTFIELDS,$data_string);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($status != 200) {
print_r([
'Error',
$status,
curl_errno($curl)
]);
}
curl_close($curl);
php-backend 只需要向 websocket 服务器发送消息,不需要接收任何消息。
解决方案
你可以让你的 php 和你的节点通过 HTTP 进行通信。
您已经在节点应用程序中安装了 express,所以让我们定义一个小 API
定义一个middleware
以确保您的 php 调用该节点API
/**
* Secure the HTTP calls from PHP
* Return a 403 (forbidden) if no token given
* */
app.use(function (req, res, next) {
// Do your logic to secure your API if your node application is visible from the internet
// You don't want malicious people to send event as your php ;)
if(false) {
res.sendStatus(403);
return;
}
next(); // it's ok let the process continue
});
定义一个在http://localhost:3000/your/endpoint上回答的简单路由GET
app.get('/your/endpoint', function(req, res) {
io.sockets.emit('update');
res.sendStatus(200);
});
如果你想使用 HTTP 请求的主体,你可以使用这样的库body-parser
来让你做下面的事情。此路由答案位于POST
http://localhost:3000/post/example
/** Enable the parsing of request body */
app.use(bodyParser.json());
app.post('/post/example', function(req, res) {
let body = req.body,
event = body.event,
data = body.data || {};
if(undefined === event) {
res.sendStatus(400);
return;
}
...
}
推荐阅读
- html - 在省电模式下,位于 HTML5 视频上的元素在 iOS 上是不可见的
- apache-kafka - Apache Kafka 和 Zookeeper [错误] [未指定路径]
- git - git rebase 如果节点有多个祖先
- excel - Excel公式查找前缀后的两个单词
- javascript - Vue - chunk-vendors.js 变得非常大
- python - 如何通过 Emukit python 包使用外部模型数据
- c++ - Arduino - 测量一个按钮按下和释放之间的时间间隔 - 将速度添加到 MIDI 键盘
- python - 带有按位逻辑运算符的python列表理解
- javascript - 如何在 useEffect 中使用 setState 中设置的新值调用函数?
- apache-spark - Pyspark:在大型数据帧上调用 .toJSON() 是最佳做法吗?