19

短いバージョン: go チャネルを再作成したりループしたりせずに空にする方法はありますか?

理由: データの送受信に 2 つのチャネルを使用しており、再接続が必要であることを通知するための追加のチャネルがあります。

トランスポートがリセット/再接続されたら、余分なチャネルを「空」にして、再接続を引き起こす他のリセット要求が残っていないことを確認します。

4

4 に答える 4

6

チャンネルに再接続するための正当な要求がある可能性があるため、あなたが説明していることは本質的に際どいものです. チャンネルを枯渇させようとするのではなく、タイミングを追跡することをお勧めします。

リコネクト チャンネルに時間を投稿します。再接続が完了したら、時間を記録します。再接続チャネルを使用している間、最後の再接続よりも古いメッセージを破棄します。

これを達成するためのもう 1 つのロックステップ ソリューションは、再接続チャネルを bool にすることです。再接続するには「true」を投稿します。再接続が完了したら、「false」を送信します。次に、「false」が見つかるまでチャネルを消費します。

于 2014-10-01T14:17:14.903 に答える
2

別のアプローチは、次の行に沿ってsync.Condand を使用しています。atomic

type Server struct {
    s     chan int
    r     chan int
    c     *sync.Cond
    state uint32
}

const (
    sNormal       = 0
    sQuitting     = 1
    sReconnecting = 2
)

func New() *Server {
    s := &Server{
        s: make(chan int),
        r: make(chan int),
        c: sync.NewCond(&sync.Mutex{}),
    }
    go s.sender()
    // go s.receiver()
    return s
}
func (s *Server) sender() {
    //
    for {
        select {
        case data := <-s.s:
        //do stuff with data
        default:
            s.c.L.Lock()
        L:
            for {
                switch atomic.LoadUint32(&s.state) {
                case sNormal:
                    break L
                case sReconnecting:
                case sQuitting:
                    s.c.L.Unlock()
                    return
                }
                s.c.Wait()
            }
            s.c.L.Unlock()
        }
    }
}

//repeat for receiver

func (s *Server) Reconnect() {
    var cannotReconnect bool
    atomic.StoreUint32(&s.state, sReconnecting)
    //keep trying to reconnect
    if cannotReconnect {
        atomic.StoreUint32(&s.state, sQuitting)
    } else {
        atomic.StoreUint32(&s.state, sNormal)
    }
    s.c.Broadcast()
}

playground

于 2014-10-01T20:05:53.870 に答える
0

リセット チャネルの代わりに、リセット ゴルーチンが必要なようです。リセット信号を送信する側からの入力と、レシーバーへの出力があります。このゴルーチンが再接続のリクエストを受け取ると、それをレシーバーに渡します。次に、受信側から 3 番目のチャネルで受信確認を受信するまで待機し、その間に受信した再接続要求をすべて破棄します。したがって、合計 3 チャネル、1 入力、1 出力、1 ACK です。

于 2014-10-01T14:20:24.117 に答える