我有多个物联网设备,带有连接到 socket.io 服务器的 socket.io 客户端。我希望客户端能够发出要备份到另一个客户端的文件并收到已完成的响应。 由于消息是从客户端到客户端的,因此必须通过服务器中继,并且由于 socket.IO 不支持广播回调,而且我知道如何将发出消息发送到特定 socket.id 的唯一方法是 io.to (socket.id).emit(),作为广播处理,我不确定如何进行。这是我的代码:
socket.io 服务器:
let connections = []
io.on("connection", (socket) => {
socket.on("disconnect", () => {
connections = connections.filter(item => item.socketId !== socket.id)
})
socket.on('setConnectionStatus', (device) => {
connections.push({device: device, socketId: socket.id})
})
//relay backup messages
socket.on('Backup', (file, callback) => {
console.log(file)
let systemController = connections.findIndex(x => x.device == 'system_controller' )
systemController = connections[systemController].socketId
io.to(systemController).emit('Backup', file, (status) => {
console.log(status)
callback(status)
})
})
})
发送 socket.io 客户端:
const socketServer = "http://10.10.10.1:3001"
const deviceName = 'liveNet'
const socket = io(socketServer)
socket.on("connect", () => {
socket.emit("setConnectionStatus", deviceName)
})
function backupToSystemController() {
return new Promise(function(resolve, _) {
const file = fs.readFileSync(__dirname + '/public/config/config.json')
socket.emit('Backup', file, (status) => {
resolve(status)
})
})
}
//this is called in an api
backupToSystemController()
接收socket.io客户端:
const socketServer = "http://10.10.10.1:3001"
const deviceName = 'system_controller'
const socket = io(socketServer)
socket.on("connect", () => {
socket.emit("setConnectionStatus", deviceName)
})
socket.on('Backup', (file, callback) => {
let response
fs.writeFile(__dirname + '/backups/config.json', file, (err) => {
if (err) {
response = {message: 'Failure' + err}
}
else {
response = {message: 'success'}
}
callback(response)
})
})
一切正常,除了服务器上的回调侦听器永远不会得到响应,因为它和我收到超时错误:
Error: operation has timed out
at Timeout._onTimeout (/home/pi/aeiProject/socketIO/server/node_modules/socket.io/dist/broadcast-operator.js:182:17)
at listOnTimeout (node:internal/timers:569:17)
at process.processTimers (node:internal/timers:512:7)
我能够通过将实际套接字推入我添加到连接数组的对象中,然后在发送发射时引用该套接字来解决这个问题。请参阅下面更新的 socket.io 服务器代码。
let connections = []
io.on("connection", (socket) => {
socket.on("disconnect", () => {
connections = connections.filter(item => item.socketId !== socket.id)
})
socket.on('setConnectionStatus', (device) => {
connections.push({device: device, socketId: socket.id, socket: socket})
})
//relay backup messages
socket.on('aeinetBackup', (file, callback) => {
let system_controller = connections.findIndex(x => x.device == 'system_controller' )
let systemControllerSocket = connections[system_controller].socket
systemControllerSocket.emit('aeinetBackup', file, (status) => { // in order to get a callback we have to use the specific socket for the system controller. Otherwise if we didn't need a callback we could use io.to(socket.id).emit()
callback(status)
})
})
})