如何使用 socket.io 从 node.js 服务器在客户端(网络浏览器)显示实时数据?
How to use socket.io to display realtime data in the client (web browser) from the node.js server?
我想在浏览器中显示实时语音转文本数据。我所说的实时是指,“在我说话的同时,我正在同时获取文本输出”。我已经使用 Google 云服务 API 在 Python 中实现了语音转文本部分。然后我在 node.js 环境中对 运行 我的 python 程序使用“子进程”。到现在为止一切都很好。接下来,我想在浏览器中显示实时文本。换句话说,我想将 python 的实时文本输出(现在是 运行ning in node.js 使用子进程)发送到 Web 浏览器。我试图用 socket.io 做到这一点。这是我的服务器端 (node.js) 代码,其中还应用了 socket.io:
const express = require('express');
//const router = express.Router();
const {spawn} = require('child_process');
const path = require('path');
const app = express();
const http = require('http');
const server = http.createServer(app);
//const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
function runScript(){
return spawn('python3', [
"-u",
path.join(__dirname, 'script.py')
]);
}
const subprocess = runScript()
// print output of the script
app.get('/', (req,res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
上面我是先用子进程调用node.js里的python程序然后用socket.broadcast.emit将 python 程序的文本输出发送到我的客户端。客户端代码如下所示:
<!DOCTYPE html>
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var messages = document.getElementById('messages');
//const EventEmitter = require('events');
//const emitter = new EventEmitter()
//emitter.setMaxListeners(50)
socket.on('messages', function(data) {
document.querySelector("#style1".innerHTML = `<p>${data1}</p>`
});
</script>
</head>
<body id="messages">
<h1> This is crazy </h1>
<div id="style1">
</div>
</body>
</html>
以上,我想在
标签内显示python程序的实时文本输出。
问题是,我无法在网络浏览器中获取任何内容。
我的 objective 是,我想在网络浏览器中实时显示我所说的任何内容。
我对socket.io了解不多。其实我也是第一次使用这个技术。
您的 Node.js 服务器将充当套接字服务器。正如您的代码所示,它在一个端口上侦听套接字连接,并在连接时创建一个套接字,然后您也可以通过该套接字发送消息。从简单粗略的审查来看,服务器代码看起来还不错。
在您的网页上,您正在创建套接字并侦听消息。
但是网页上的套接字 运行 还没有连接到服务器,这就是为什么还没有任何工作的原因。
假设您在本地主机上执行此操作,只需将套接字服务器地址添加到它的构造函数中,然后监听连接。
const socket = io('ws://localhost:3000');
socket.on('connect', () => {
// do any authentication or handshaking here.
console.log('socket connected');
});
更高级的实现应该优雅地处理关闭套接字。
根据以下评论:
I added the lines you suggested above. Even now nothing is visible on the webpage but I am getting this warning: (node:14016) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message listeners added. Use emitter.setMaxListeners() to increase limit
仔细查看您的服务器代码,我相信这是根本问题
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
每次您从 subprocess.stdout
接收数据时,您都在向您的套接字添加一个新的 onmessage
事件处理程序,因此一段时间后,您添加了太多的事件处理程序。
重写你的逻辑,这样你只添加 socket.on('message')
一次(通常在你创建套接字之后)。
还值得注意的是,在上面的代码中,没有使用来自 stdout 的 data
,因为 data
变量正在由您的 onmessage
在较低的范围内重新定义功能。由于正在重新定义数据,Python 程序的输出将被忽略。
我想这就是你想要的:
//echo any message you receive from the socket back to the socket
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
//send data from std out to the socket.
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.broadcast.emit('message', data);
});
我想在浏览器中显示实时语音转文本数据。我所说的实时是指,“在我说话的同时,我正在同时获取文本输出”。我已经使用 Google 云服务 API 在 Python 中实现了语音转文本部分。然后我在 node.js 环境中对 运行 我的 python 程序使用“子进程”。到现在为止一切都很好。接下来,我想在浏览器中显示实时文本。换句话说,我想将 python 的实时文本输出(现在是 运行ning in node.js 使用子进程)发送到 Web 浏览器。我试图用 socket.io 做到这一点。这是我的服务器端 (node.js) 代码,其中还应用了 socket.io:
const express = require('express');
//const router = express.Router();
const {spawn} = require('child_process');
const path = require('path');
const app = express();
const http = require('http');
const server = http.createServer(app);
//const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
function runScript(){
return spawn('python3', [
"-u",
path.join(__dirname, 'script.py')
]);
}
const subprocess = runScript()
// print output of the script
app.get('/', (req,res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
上面我是先用子进程调用node.js里的python程序然后用socket.broadcast.emit将 python 程序的文本输出发送到我的客户端。客户端代码如下所示:
<!DOCTYPE html>
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var messages = document.getElementById('messages');
//const EventEmitter = require('events');
//const emitter = new EventEmitter()
//emitter.setMaxListeners(50)
socket.on('messages', function(data) {
document.querySelector("#style1".innerHTML = `<p>${data1}</p>`
});
</script>
</head>
<body id="messages">
<h1> This is crazy </h1>
<div id="style1">
</div>
</body>
</html>
以上,我想在
标签内显示python程序的实时文本输出。 问题是,我无法在网络浏览器中获取任何内容。 我的 objective 是,我想在网络浏览器中实时显示我所说的任何内容。
我对socket.io了解不多。其实我也是第一次使用这个技术。
您的 Node.js 服务器将充当套接字服务器。正如您的代码所示,它在一个端口上侦听套接字连接,并在连接时创建一个套接字,然后您也可以通过该套接字发送消息。从简单粗略的审查来看,服务器代码看起来还不错。
在您的网页上,您正在创建套接字并侦听消息。
但是网页上的套接字 运行 还没有连接到服务器,这就是为什么还没有任何工作的原因。
假设您在本地主机上执行此操作,只需将套接字服务器地址添加到它的构造函数中,然后监听连接。
const socket = io('ws://localhost:3000');
socket.on('connect', () => {
// do any authentication or handshaking here.
console.log('socket connected');
});
更高级的实现应该优雅地处理关闭套接字。
根据以下评论:
I added the lines you suggested above. Even now nothing is visible on the webpage but I am getting this warning: (node:14016) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message listeners added. Use emitter.setMaxListeners() to increase limit
仔细查看您的服务器代码,我相信这是根本问题
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
每次您从 subprocess.stdout
接收数据时,您都在向您的套接字添加一个新的 onmessage
事件处理程序,因此一段时间后,您添加了太多的事件处理程序。
重写你的逻辑,这样你只添加 socket.on('message')
一次(通常在你创建套接字之后)。
还值得注意的是,在上面的代码中,没有使用来自 stdout 的 data
,因为 data
变量正在由您的 onmessage
在较低的范围内重新定义功能。由于正在重新定义数据,Python 程序的输出将被忽略。
我想这就是你想要的:
//echo any message you receive from the socket back to the socket
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
//send data from std out to the socket.
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.broadcast.emit('message', data);
});