(Go) Сравнение постоянно меняющейся переменной в цикле ws

Работая над циклом, который получает сообщения и обрабатывает их соответствующим образом, в основном это эхо-эхо-сервер веб-сокета с поддержкой активности и аутентификацией, и я некоторое время застрял в части поддержки активности.

Концепция проста: когда сервер запускается, я создаю горутин с тикером и инициализирую указатель uint64, каждый раз, когда тиккер тикает (каждые 2 секунды), я увеличиваю указатель с помощью atomic.AddUint64(clockTicks, 1), затем для каждой горутины подключения к веб-сокету я проверяю переменную каждый тик с помощью сравнения и atomic.LoadUint64 (clockTicks) и отправляю сообщение ping/pong.

Изменить: похоже, что что-то блокирует цикл for до тех пор, пока не будет получено сообщение, результат:

i := atomic.LoadUint64(clockTicks)
    if i != cur {
        cur = i
        if act != true {
            fmt.Println("Quit Nao U filthy bot.")
            return
        } else {
            fmt.Println("Keep Going.")
            act = false
        }
    }

В этом фрагменте я := atomic.LoadUint64(clockTicks) и весь блок if запускается только при отправке сообщения i (печатает «Продолжить» в msg), а это не то, что я хочу, я хочу, чтобы фрагмент выполнялся каждый раз. для итерации и «Продолжить». & "Quit nao ...", чтобы запускать каждый раз, когда clockTicks увеличивается

Вот важные части кода, я использую библиотеку веб-сокетов Go и Gorilla:

func Clock() {
clockTicks = new(uint64)
*clockTicks = 0
clock := time.NewTicker(authIntervals).C
for {
    <-clock
    atomic.AddUint64(clockTicks, 1)
}
}

var wsu = websocket.Upgrader{
ReadBufferSize:  1024,
WriteBufferSize: 1024,
CheckOrigin:     OriginHandler,
}

func serveWS(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
    http.Error(w, "Method not allowed", 405)
    return
}

ws, err := wsu.Upgrade(w, r, nil)
if err != nil {
    fmt.Println(err)
    return
}

defer ws.Close()
cur := atomic.LoadUint64(clockTicks)
var act, val = true, false
for {
    i := atomic.LoadUint64(clockTicks)
    if i != cur { /* Only triggers when I receive a msg */
        cur = i
        if act != true {
            fmt.Println("Quit Nao U filthy bot.")
            return
        } else {
            fmt.Println("Keep Going.")
            act = false
        }
    }

    mtype, p, err := ws.ReadMessage()
    if err != nil {
        return
    }

    ...

}

Редактировать 2: кто-то в IRC предположил, что, возможно, блокирует ws.ReadMessage, но я не совсем уверен (он говорит, что ioutil.ReadAll, используемый в реализации ws.ReadMessage, блокирует его, и он в этом почти уверен)


person Whiteclaws    schedule 01.11.2015    source источник


Ответы (1)


Методы чтения через веб-сокет вызывают метод чтения сетевого подключения для получения данных из сети. Поскольку метод Read сетевого подключения блокируется, методы webcocket также блокируются.

Для отправки пингов используйте тикер в цикле записи как в примере с чатом Gorilla, или запустите отдельную горутину для проверки связи как в примере команды Gorilla.

person Cerise Limón    schedule 01.11.2015
comment
Нет ли способа получать сообщения без блокировки? - person Whiteclaws; 02.11.2015
comment
@Whiteclaws Невозможно получить данные из сетевого подключения без блокировки. Вы можете написать цикл чтения, который отправляет сообщения на канал, где получатель на этом канале использует select, чтобы избежать блокировки (см. Пример чата Gorilla). - person Cerise Limón; 02.11.2015