如何将消息发送到池中的所有连接

时间:2019-03-17 14:00:13

标签: go websocket server-sent-events go-gin

将服务器端事件添加到流中后,如何确保当前连接到该流的所有客户端都接收该事件,即如何在丢弃消息之前遍历所有客户端并向他们发送消息,这是这个吗?甚至可以用sse和Go吗?

我想在下面实现的摘要伪代码

package main

import (
    "github.com/gin-contrib/sse"
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {

    router := gin.New()
    router.Use(gin.Logger())

    var events = make(chan sse.Event, 100)

    router.GET("/api/addUser/event", func(c *gin.Context) {

        c.Header("Content-Type", "text/event-stream")
        c.Header("Access-Control-Allow-Origin", "*")
        c.Header("Access-Control-Allow-Headers", "access-control-allow-origin, access-control-allow-headers")

        // if events chan has an event
        // Send event to all connected clients

        if( we have events then send them to all clients){

            event := <-events
            _ = sse.Encode(c.Writer, event)
        }

    })

    router.POST("/api/addUser", func(c *gin.Context) {

        //On user add
        //Add event to events chan
        events <- sse.Event{
            Event: "newChiitiko",
            Id:    "1",
            Data:  "New Chiitiko Event",
        }

        c.JSON(http.StatusOK, "okay")
    })

    _ = router.Run(":5000")
}

1 个答案:

答案 0 :(得分:0)

使用单个频道很难做到。最简单的答案是为每个连接创建通道。

赞:

mu := new(sync.Mutex)
var eventChans []sse.Event

router.GET("/api/addUser/event", func(c *gin.Context) {
    c.Header("Content-Type", "text/event-stream")
    c.Header("Access-Control-Allow-Origin", "*")
    c.Header("Access-Control-Allow-Headers", "access-control-allow-origin, access-control-allow-headers")

    // Add own channel to the pool.
    events := make(chan sse.Event)
    mu.Lock()
    eventChans = append(eventChans, events)
    mu.Unlock()

    // Listen for the events.
    for(event := range events) {
        sse.Encode(c.Writer, event)
    }
})

router.POST("/api/addUser", func(c *gin.Context) {
    mu.Lock()
    for(_, events := range eventChans) {
        events <- sse.Event{ ... }
    }
    mu.Unlock()

    c.JSON(http.StatusOK, "okay")
})

或使用sync.Cond。

cond := sync.NewCond(new(sync.Mutex))
var event *sse.Event

router.GET("/api/addUser/event", func(c *gin.Context) {
    c.Header("Content-Type", "text/event-stream")
    c.Header("Access-Control-Allow-Origin", "*")
    c.Header("Access-Control-Allow-Headers", "access-control-allow-origin, access-control-allow-headers")

    for {
        // Wait for event.
        cond.L.Lock()
        for(event == nil) {
            cond.Wait()
        }

        sse.Encode(c.Writer, event)
    }
})

router.POST("/api/addUser", func(c *gin.Context) {
    cond.L.Lock()
    event = sse.Event{ ... }
    cond.L.Unlock()

    cond.Broadcast()

    c.JSON(http.StatusOK, "okay")
})