HTTP处理函数返回后,如何保持WebSocket连接打开?

I'm trying to write code to stream data on a topic, like a radio station (one broadcaster, several listeners). I'm stuck on how to process a new WebSocket connection request without having a goroutine for each open WebSocket (that starts to get resource-intensive for many "listeners" to the same "station").

At the moment, I have a map of dataStream structs which look like this:

struct dataStream {
  data chan byte[]
  conns []*websocket.Connection
}

And here's the pseudocode for upgrading the request to a WebSocket, and then attempting to add a WebSocket connection to the dataStreams conns:

func process_request(w http.ResponseWriter, r *http.Request) {
  // hundred lines of business logic...
  c := upgrade websocket connection
  defer c.Close()
  if dataStream exists {
    append the new connection c to the dataStream.conns slice
  } else {
    create new dataStream
    append the new connection c to the dataStream.conns slice
    stream(dataStream)
  }
}

And then here's the stream function mentioned in the above code block. One of these runs in the background for each dataStream (not for every WebSocket connection).

func stream(ds *dataStream) {
  ticker := time.NewTicker(poll every ~10 seconds)
  go func() { // this is to poll and remove closed connections
  for _ = range ticker.C {
    for traverse ds.conns {
      ping all connections, remove any closed ones and free memory
      if len(ds.conns == 0){ // no more connections are listening to this dataStream
        delete the ds dataStream and free the memory
        stop ticker
        return // kill goroutine and free the memory
      }
    }
  }}()
  while len(ds.conns) != 0 { // while there are open connections
    fetch any available <-ds.data from channel
    write the data as websocket message to each connection
  }
}

The trouble with this approach is that in the process_request function, as soon as the flow reaches the bottom if statement of the 2nd and subsequent connections, after the new connection is appended to the dataStream.conns slice the function terminates closing the WebSocket connection! As a result, stream() is running in the background and polls that a closed connection has been added to the ds.conns slice and removes it.

Hence my question:

What approach should I take to maintain the WebSocket connection open for even after the process_request handler function returns, preferentially without running a separate goroutine for each connection?

dopzc64662
dopzc64662 令人沮丧很抱歉打扰你们两个。@Thundercat您对Gorilla连接的持久性绝对正确。当我尝试切掉实际代码的无关紧要的内容以便发布时,我注意到所有样板连接创建代码的顶部都推迟了c.Close()。抱歉浪费您的时间。我已将该行添加到伪代码中,以便您至少可以创建答案并获得好评。
接近 2 年之前 回复
douzhuoxia0587
douzhuoxia0587 感谢您对大猩猩保持连接打开的评论。我将用一个简化的版本替换伪代码,该版本不会太长,因此您可能能够看到关闭它的原因。
接近 2 年之前 回复
duan0504
duan0504 应用程序必须显式关闭Gorilla连接。HTTP处理函数返回时,连接不会自动关闭。发生了其他事情。因为您有750行代码,所以我将从种族探测器开始。它可能指出了问题。
接近 2 年之前 回复
douli1854
douli1854 如果可以看到产生该问题的代码,我很乐意尝试找出问题所在。
接近 2 年之前 回复
dongsong1911
dongsong1911 您能建议Go和Gorilla做到这一点的方法吗?该库不能在操场上导入。
接近 2 年之前 回复
doumei9589
doumei9589 使用伪代码解决特定问题几乎是不可能的。请尝试创建一个(最小,完整,可验证的示例)[stackoverflow.com/help/mcve]演示您的问题。
接近 2 年之前 回复
dongnong3019
dongnong3019 实际代码约为750行,因此我使用了伪代码。问题在于处理http请求并将其转换为websocket连接的方式,而不是语法本身(编译良好)。
接近 2 年之前 回复
douhao8456
douhao8456 我按照推荐的方式使用了Gorilla库,并且据我了解,升级http请求是正常的做法。
接近 2 年之前 回复
dqyym3667
dqyym3667 如果您使用的是Gorilla,则返回process_request不会关闭连接。其他可能会关闭连接,但不是从处理程序返回的原因。因为您没有共享实际的代码,所以很难对可能出问题的地方进行评论。我建议使用竞赛检测器运行该应用程序并修复其报告的所有问题。
接近 2 年之前 回复
doulingna9420
doulingna9420 net/http请求处理程序用于处理HTTP请求,而不用于管理WebSocket连接。请查看godoc.org/golang.org/x/net/websocket以获取标准库解决方案,或从该文档链接的库以获取更完整的第三方解决方案。
接近 2 年之前 回复

1个回答



应用程序必须显式关闭Gorilla连接。 HTTP处理函数返回时,连接不会自动关闭。 </ p>

在这种情况下,应用程序使用defer语句在从处理程序返回时关闭连接。 删除defer语句,以避免关闭连接。</ p>
</ div>

展开原文

原文

The application must explicitly close a Gorilla connection. The connection is not automatically closed when the HTTP handler function returns.

In this case, the application uses a defer statement to close the connection on return from the handler. Delete the defer statement to avoid closing the connection.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问