我有一个使用socket.io在长时间的HTTP请求期间传输一些消息的node.js服务和angular客户端。
服务:
通常情况下它们工作正常,但会随机产生断开连接错误。从我的日志文件中可以看到这个问题:
同时,在断开连接的消息出现的时候,前端还注意到了一个称为“transport close”的断开事件。
从日志中我们可以看到工作流程如下:
1. 前端启动了一个 socket 连接并向后端发送了一个初始化消息。它也保存了这个 socket。 2. 后端检测到了连接并收到了初始化消息。 3. 后端将该 socket 放入数组中,以便随时随地使用。 4. 第一个 socket 意外断开连接,另一个连接被发布,前端不知情,因此前端从未发送过初始化消息。 5. 由于前端保存的 socket 没有改变,当它进行 http 请求时,它使用了旧的 socket ID。结果,后端使用已从 socket 数组中删除的旧 socket 发送了消息。
这种情况并不经常发生。有人知道是什么原因导致了断开连接和未知连接问题吗?
服务:
export const socketArray: SocketIO.Socket[] = [];
export let socketMapping: {[socketId: string]: number} = {};
const socketRegister: hapi.Plugin<any> = {
register: (server) => {
const io: SocketIO.Server = socket(server.listener);
// Whenever a session connected to socket, create a socket object and add it to socket array
io.on("connection", (socket) => {
console.log(`socket ${socket.id} connected`);
logger.info(`socket ${socket.id} connected`);
// Only put socket object into array if init message received
socket.on("init", msg => {
logger.info(`socket ${socket.id} initialized`);
socketArray.push(socket);
socketMapping[socket.id] = msg;
});
// Remove socket object from socket array when disconnected
socket.on("disconnect", (reason) => {
console.log(`socket ${socket.id} disconnected because: ${reason}`)
logger.info(`socket ${socket.id} disconnected because: ${reason}`);
for(let i = 0; i < socketArray.length; i ++) {
if(socketArray[i] === socket) {
socketArray.splice(i, 1);
return;
}
}
});
});
},
name: "socketRegister",
version: "1.0"
}
export const socketSender = async (socketId: string, channel: string, content: SocketMessage) => {
try {
// Add message to db here
// await storeMessage(socketMapping[socketId], content);
// Find corresponding socket and send message
logger.info(`trying sending message to ${socketId}`);
for (let i = 0; i < socketArray.length; i ++) {
if (socketArray[i].id === socketId) {
socketArray[i].emit(channel, JSON.stringify(content));
logger.info(`socket ${socketId} send message to ${channel}`);
if (content.isFinal == true) {
// TODO: delete all messages of the process if isFinal is true
await deleteProcess(content.processId);
}
return;
}
}
} catch (err) {
logger.error("Socket sender error: ", err.message);
}
};
客户:
connectSocket() {
if (!this.socket) {
try {
this.socket = io(socketUrl);
this.socket.emit('init', 'some-data');
} catch (err) {
console.log(err);
}
} else if (this.socket.disconnected) {
this.socket.connect();
this.socket.emit('init', 'some-data');
}
this.socket.on('some-channel', (data) => {
// Do something
});
this.socket.on('disconnect', (data) => {
console.log(data);
});
}
通常情况下它们工作正常,但会随机产生断开连接错误。从我的日志文件中可以看到这个问题:
2018-07-21T00:20:28.209Z[x]INFO: socket 8jBh7YC4A1btDTo_AAAN connected
2018-07-21T00:20:28.324Z[x]INFO: socket 8jBh7YC4A1btDTo_AAAN initialized
2018-07-21T00:21:48.314Z[x]INFO: socket 8jBh7YC4A1btDTo_AAAN disconnected because: ping timeout
2018-07-21T00:21:50.849Z[x]INFO: socket C6O7Vq38ygNiwGHcAAAO connected
2018-07-21T00:23:09.345Z[x]INFO: trying sending message to C6O7Vq38ygNiwGHcAAAO
同时,在断开连接的消息出现的时候,前端还注意到了一个称为“transport close”的断开事件。
从日志中我们可以看到工作流程如下:
1. 前端启动了一个 socket 连接并向后端发送了一个初始化消息。它也保存了这个 socket。 2. 后端检测到了连接并收到了初始化消息。 3. 后端将该 socket 放入数组中,以便随时随地使用。 4. 第一个 socket 意外断开连接,另一个连接被发布,前端不知情,因此前端从未发送过初始化消息。 5. 由于前端保存的 socket 没有改变,当它进行 http 请求时,它使用了旧的 socket ID。结果,后端使用已从 socket 数组中删除的旧 socket 发送了消息。
这种情况并不经常发生。有人知道是什么原因导致了断开连接和未知连接问题吗?