猿问

如何在没有比赛的情况下延长自动收报机的持续时间?

我正在尝试实现一个 keepAlive 机制。问题是我不知道如何在没有竞争的情况下替换保持活动的股票代码 (conn.keepAlive),因为keepAlive()方法总是从股票代码中读取。


//errors not handled for brevity

const interval = 10 * time.Second


type conn struct {

    keepAlive time.Ticker

    conn      net.Conn

    mux       sync.Mutex

}


// replace replaces the underlying connection

func (cn conn) replace(newcn net.Conn) {

    cn.mux.Lock()

    cn.conn = newcn

    // reset the ticker

    cn.keepAlive.Stop

    cn.keepAlive = time.NewTicker(interval)

    cn.mux.Unlock()

}


func (cn conn) keepAlive() {

    for {

        <-cn.keepAlive.C

        cn.mux.Lock()

        cn.conn.Write([]byte("ping"))

        var msg []byte

        cn.conn.Read(msg)

        if string(msg) != "pong" {

            // do some mean stuff

        }

        cn.keepAlive = time.NewTicker(interval)

        cn.mux.Unlock()

    }

}


白衣染霜花
浏览 145回答 2
2回答

神不在的星期二

更简洁地实现这一点的一种方法是使用通道作为同步机制,而不是互斥锁:type conn struct {&nbsp; &nbsp; sync.Mutex&nbsp; &nbsp; conn&nbsp; &nbsp; &nbsp; &nbsp; net.Conn&nbsp; &nbsp; replaceConn chan net.Conn}// replace replaces the underlying connectionfunc (cn *conn) replace(newcn net.Conn) {&nbsp; &nbsp; cn.replaceConn <- newcn}func (cn *conn) keepAlive() {&nbsp; &nbsp; t := time.NewTicker(interval)&nbsp; &nbsp; msg := make([]byte, 10)&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-t.C:&nbsp; &nbsp; &nbsp; &nbsp; case newConn := <-cn.replaceConn:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.Lock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.conn = newConn&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; cn.Lock()&nbsp; &nbsp; &nbsp; &nbsp; _ = msg&nbsp; &nbsp; &nbsp; &nbsp; // do keepalive&nbsp; &nbsp; &nbsp; &nbsp; cn.Unlock()&nbsp; &nbsp; }}

富国沪深

我最终得到了下面的代码。我对它的样子不太满意,但它确实有效。基本上我将复用器包裹在一个通道中,以便我可以对其进行选择。const interval = 10 * time.Secondtype conn struct {&nbsp; &nbsp; keepAlive time.Ticker&nbsp; &nbsp; conn&nbsp; &nbsp; &nbsp; *net.Conn&nbsp; &nbsp; mux&nbsp; &nbsp; &nbsp; &nbsp;sync.Mutex}// replace replaces the underlying connectionfunc (cn conn) replace(newcn *net.Conn) {&nbsp; &nbsp; cn.mux.Lock()&nbsp; &nbsp; cn.conn = newcn&nbsp; &nbsp; // reset the ticker&nbsp; &nbsp; cn.keepAlive.Stop&nbsp; &nbsp; cn.keepAlive = time.NewTicker(interval)&nbsp; &nbsp; cn.mux.Unlock()}func (cn conn) keepAlive() {&nbsp; &nbsp; lockerFn := func() <-chan struct{} {&nbsp; &nbsp; &nbsp; &nbsp; cn.mux.Lock()&nbsp; &nbsp; &nbsp; &nbsp; ch = make(chan struct{})&nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ch <- struct{}{}&nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; &nbsp; &nbsp; return ch&nbsp; &nbsp; }&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; locker := lockerFn()&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-cn.keepAlive.C:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // unlock the locker otherwise we&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // get stuck&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <-locker&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.mux.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; &nbsp; &nbsp; case <-locker:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.conn.Write([]byte("ping"))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var msg []byte&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.conn.Read(msg)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.keepAlive = time.NewTicker(interval)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cn.mux.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Go
我要回答