关于此规范:http://www.w3.org/TR/eventsource/
如何关闭服务器上打开的连接?客户端方面很容易,只需调用close()
,但我应该在服务器上做什么?只是杀了它?
答案 0 :(得分:2)
的node.js:
http.createServer(function (req, res) {
//...
// client closes connection
res.socket.on('close', function () {
res.end();
//...
});
});
请参阅node.js中实现SSE服务器的示例:
https://github.com/Yaffle/EventSource/blob/master/nodechat/server.js
答案 1 :(得分:2)
您可以更改“text / event-stream”以外的服务器sents的内容类型。 这将关闭客户端事件源。
答案 2 :(得分:1)
我猜你只是关闭连接(杀死它)。我还没有看到任何有关优雅断开的话题。
答案 3 :(得分:0)
警告:如果您使用程序包来管理node.js中服务器发送的事件,则直接调用response.end()
可能导致程序包在{{1之后}},这将导致服务器崩溃,并显示“ 关闭后写入”错误。
我的解决方法是直接调用response.end()
,而不是直接调用response.end()
,这使程序包可以处理关闭。
Node.js文档:
答案 4 :(得分:0)
res.end()并不是可行的方法,以后可能会导致ERR_STREAM_WRITE_AFTER_END错误。如果是这种情况,最好撤消在路由中添加的逻辑。
答案 5 :(得分:0)
因此,我一直在寻找该协议中内置的解决方案,但似乎没有一个解决方案。如果您的服务器调用response.emit('close')
或response.end()
,则客户端会将其视为错误,并尝试重新连接到服务器。 (至少对于Chrome,除非它认为网络错误是致命的,否则它将尝试无限期地重新连接。)
看来,您的客户端必须以一种或另一种方式关闭连接。剩下两个选择。首先,是简单地假设服务器出现任何错误都应关闭EventSource。
const sse = new EventSource('/events')
sse.onmessage = m => console.log(m.data)
sse.onerror = () => sse.close()
以上内容仍然有一些需要改进的地方。我们假设网络错误是正常关闭,但事实并非如此。在某些情况下,我们要做想要重新连接行为。
因此,为什么我们不只是要求客户端正常关闭自身!我们有一种从服务器向客户端发送消息的方法,因此我们要做的就是从服务器发送一条消息,说“关闭我”。
// client.js
const maxReconnectTries = 3
let reconnectAttempts = 0
const sse = new EventSource('/events')
sse.onmessage = m => {
const { type, data } = JSON.parse(m.data)
if (type === 'close') sse.close()
else console.log(data)
}
sse.onerror = () => {
if (reconnectAttempts > maxReconnectTries) {
sse.close()
alert("We have a baaad network error!")
} else {
reconnectAttempts++
}
}
// server.js
const express = require('express')
function sendEvent(res, type, data) {
res.write(`data: ${JSON.stringify({ type, data })}\n\n`)
}
function sseHandler(req, res) {
response.writeHead(200, {
'Connection': 'keep-alive',
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache'
}
let manualShutdown
request.on('close', () => {
console.log('disconnected.')
clearTimeout(manualShutdown) // prevent shutting down the connection twice
})
sendEvent(res, 'message', `Ping sent at ${new Date()}`)
// when it comes time to shutdown the event stream (for one reason or another)
setTimeout(() => {
sendEvent(res, 'close', null)
// give it a safe buffer of time before we shut it down manually
manualShutdown = setTimeout(() => res.end(), clientShutdownTimeout)
}, 10000)
}
const clientShutdownTimeout = 2000
const app = express()
app.get('/events', sseHandler)
app.listen(4000, () => console.log('server started on 4000'))
这涵盖了我们安全实施客户端/服务器所需的所有领域。如果服务器上有问题,我们会尝试重新连接,但是如果出现故障,仍然可以通知客户端。当服务器希望关闭连接时,它要求客户端关闭连接。两秒钟后,如果客户端没有关闭连接,我们可以假设出现问题并关闭连接服务器端。
我们在这里所做的是在服务器发送的事件之上构建协议。它有一个非常简单的API:{ "type": "close" }
告诉客户端关闭服务器,而{ "type": "message", "data": {"some": "data" }
告诉客户端这是一条常规消息。