server-sent events Golang

huangapple go评论76阅读模式
英文:

server-sent events Golang

问题

我想进行一些单向数据流的实验,并且正在尝试使用SSE和Websockets。

在使用golang服务器的SSE时,我发现在会话结束时如何通知客户端很困惑(例如,服务器已完成事件发送,服务器突然下线或客户端失去连接)。

我需要的一件事是可靠地知道这些断开连接的情况,而不使用超时等机制。
到目前为止,我的实验结果是,当我将服务器下线时,客户端会收到EOF。但是我在尝试弄清楚如何从服务器向客户端发出信号,表示连接已关闭/完成,然后如何处理/读取它时遇到了问题?EOF是否是确定关闭/错误/完成状态的可靠方法?

许多SSE示例未能展示良好的客户端连接处理。

使用Websockets会更容易吗?

非常感谢任何经验和建议。

谢谢

英文:

I would like to do some one way streaming of data and am experimenting with SSE vs Websockets.

Using SSE form a golang server I'm finding it confusing on how to notify the client when sessions are finished. (eg the server has finished sending the events or the server suddenly goes offline or client looses connectivity)

One thing I need is to reliably know when these disconnect situations. Without using timeouts etc.
My experiments so far , when I take the server offline the client gets EOF. But I'm having trouble trying to figure out how to signal from the server to the client that a connection is closed / finished and then how to handle / read it? Is EOF a reliable way to determine a closed / error / finished state?

Many of the examples with SSE fail to show client good client connection handling.

Would this be easier with Websockets?

Any experiences suggestions most appreciated.

Thanks

答案1

得分: 3

SSE标准要求浏览器在连接丢失或服务器故意关闭套接字后,自动在N秒后重新连接(在我上次检查时,Firefox默认为5秒,Chrome和Safari默认为3秒)。所以,如果这是可取的,你不需要做任何事情。(在WebSockets中,你需要自己实现这种重新连接。)

如果不希望进行这种重新连接,你应该向客户端发送一条消息,告诉它“节目结束,请离开”。例如,如果你正在流式传输金融数据,你可以在星期五晚上市场关闭时发送这条消息。然后客户端应该拦截这条消息并从自己的一侧关闭连接。(套接字将会消失,所以服务器进程将自动关闭。)

在JavaScript中,假设你正在使用JSON发送数据,代码如下:

var es = EventSource("/datasource");
es.addEventListener("message", function(e){
  var d = JSON.parse(e.data);
  if(d.shutdownRequest){
    es.close();
    es=null;
    //告诉用户刚刚发生了什么。
  }
  else{
    //正常处理逻辑
  }
}, false);

更新:

你可以通过监听“close”事件,并查看e.target.readyState来了解重新连接的发生时间。

es.addEventListener("error", handleError, false);
function handleError(e){
  if(e.target.readyState == 0)console.log("重新连接中...");
  if(e.target.readyState == 2)console.log("放弃重连。");
}

没有其他可用的信息,更重要的是它无法区分是你的服务器进程故意关闭连接、你的Web服务器崩溃还是客户端的互联网连接中断。

另外,你可以通过让服务器发送retry:NN消息来自定义重试时间。所以,如果你不想进行快速重新连接,而是希望在任何重新连接尝试之间至少间隔60秒,请让你的服务器发送retry:60

英文:

The SSE standard requires that the browser reconnect, automatically, after N seconds, if the connection is lost or if the server deliberately closes the socket. (N defaults to 5 in Firefox, 3 in Chrome and Safari, last time I checked.) So, if that is desirable, you don't need to do anything. (In WebSockets you would have to implement this kind of reconnect for yourself.)

If that kind of reconnect is not desirable, you should instead send a message back to the client, saying "the show is over, go away". E.g. if you are streaming financial data, you might send that on a Friday evening, when the markets shut. The client should then intercept this message and close the connection from its side. (The socket will then disappear, so the server process will automatically get closed.)

In JavaScript, and assuming you are using JSON to send data, that would look something like:

var es = EventSource("/datasource");
es.addEventListener("message", function(e){
  var d = JSON.parse(e.data);
  if(d.shutdownRequest){
    es.close();
    es=null;
    //Tell user what just happened.
    }
  else{
    //Normal processing here
    }
  },false);

UPDATE:

You can find out when the reconnects are happening, by listening for the "close" event, then looking at the e.target.readyState

es.addEventListener("error", handleError, false);
function handleError(e){
  if(e.target.readyState == 0)console.log("Reconnecting...");
  if(e.target.readyState == 2)console.log("Giving up.");
  }

No other information is available, but more importantly it cannot tell the difference between your server process deliberately closing the connection, your web server crashing, or your client's internet connection going down.

One other thing you can customize is the retry time, by having the the server send a retry:NN message. So if you don't want quick reconnections, but instead want at least 60 seconds between any reconnect attempts do this have your server send retry:60.

huangapple
  • 本文由 发表于 2015年7月7日 20:31:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/31268628.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定