Ошибка websocket: close sent
указывает, что сервер отправил клиенту сообщение о закрытии.Поскольку код сервера приложений не отправляет сообщение, сообщение должно быть отправлено соединением в ответ на закрытое сообщение от клиента.
Сообщение о закрытии возвращается как ошибка из методов чтения websocket.Поскольку нет зарегистрированных сообщений, клиент должен был отправить закрывающее сообщение «уходящий» (единственная ошибка не зарегистрирована).
Когда соединение веб-сокета возвращает ошибку, программы чтения и записи закрывают соединение ивернуть.Соединение не оставлено открытым.
Функции чтения и записи не обнаруживают, что другой закрыл соединение, пока не будет возвращена ошибка из вызова метода соединения.Программа чтения быстро обнаруживает закрытое соединение, потому что она всегда читает, но для программы записи может быть задержка.Это может быть проблемой для приложения
Чтобы быстро завершить запись программы, сигнализируйте программу записи с помощью канала.Возможно, что dataChan
может использоваться для этой цели, но я точно не знаю, потому что вопрос не включает информацию о том, как управляется канал.Предполагая, что канал можно использовать, программа чтения должна закрыться dataChan
.Автор должен обнаружить закрытый канал и выйти из программы:
...
for {
select {
case data, ok := <-datachan:
if !ok {
// Done writing, return
return
}
ws.SetWriteDeadline(time.Now().Add(writeWait))
err := ws.WriteJSON(&data)
if err != nil {
conf.Log.Debugf("Failed to write data to Websocket: %v", err)
return
}
...
Этот подход используется в примере Gorilla Chat .
Если dataChan
невозможноиспользовать, ввести новый канал только для этой цели.Создайте канал в обработчике и передайте его в программу чтения и записи:
done := make(chan struct{})
go allUserWebsocketWriter(ws, stop, datachan)
go PingResponse(ws, stop)
Закройте канал при возврате из процедуры чтения:
func PingResponse(ws *websocket.Conn, done chan struct{}) {
defer close(done)
conf := storage.GetConfig()
...
Выберите канал взаписывающая программа:
...
for {
select {
case <-done:
return
case data := <-datachan:
ws.SetWriteDeadline(time.Now().Add(writeWait))
err := ws.WriteJSON(&data)
...
Это заставляет записывающую программу быстро завершать работу после завершения считывающей программы.
Этот подход используется в примере команды Gorilla .
Оба эти подхода снижают вероятность того, что запись в соединение возвращает ошибку websocket: close sent
, но онине исключайте возможность.Ошибка ожидается, потому что программа чтения может закрыть соединение непосредственно перед тем, как программа записи пишет сообщение.
В любом случае, доказательство состоит в том, что клиент закрывает соединение.Незащищенные соединения - это не проблема.