title: Close sent on server side but client side has still connection
body: <p>I have an application that communicates over an API and a websocket.
  The websocket is used to publish updated userdata to the client if it is changed in the database - this works perfectly, except for the case that the websocket does not receive any data in some cases. After a few seconds, the websocket starts working again.</p>
  <p>The server log (first, the websocket does not work and starts working again)</p>
  <blockquote>
  <p>msg=&quot;Failed to write data to Websocket: websocket: close sent&quot;</p>
  <p>msg=&quot;Sending Ping Message to Client&quot;</p>
  <p>msg=&quot;Failed to write ping message to Websocket: websocket: close sent&quot;</p>
  <p>msg=&quot;Sending Ping Message to Client&quot;</p>
  <p>msg=&quot;Sending Ping Message to Client&quot;</p>
  <p>msg=&quot;Sending Ping Message to Client&quot;</p>
  <p>msg=&quot;Sending Ping Message to Client&quot;</p>
  </blockquote>
  <p>The client-side code:</p>
  <pre><code>&lt;html&gt;
  &lt;body&gt;
  &lt;p id=&quot;data&quot;&gt;&lt;/p&gt;
  &lt;/body&gt;
  &lt;script&gt;
  var ws = new WebSocket(&quot;wss://example.com/ws&quot;);
  
  function unloadPage() {
      toggleLoader();
      ws.onclose = function () {};
      ws.close();
  }
  
  ws.onopen = function () {
      ws.send('Ping');
  };
  ws.onerror = function (error) {
      console.log('WebSocket Error ' + error);
      var d = document.getElementById(&quot;data&quot;);
      d.innerHTML += &quot;&lt;tr&gt;&lt;td&gt;Failed to connect to Server.&lt;/td&gt;&lt;/tr&gt;&quot;
  };
  ws.onmessage = function (e) {
      console.log(e);
      var data = e.data;
      var d = document.getElementById(&quot;data&quot;);
      var parsedjson = JSON.parse(data);
      d.innerHTML = &quot;&quot;;
      for (var i = 0; i &lt; parsedjson.length; i++) {
          d.innerHTML += parsedjson;
      }
  };
  ws.onclose = function () {
      console.log(&quot;Websocket has been closed&quot;);
  };
  window.addEventListener(&quot;beforeunload&quot;, unloadPage);
  &lt;/script&gt;
  &lt;/html&gt;
  </code></pre>
  <p>The Go Code (routed through gorilla mux):</p>
  <pre><code>var (
      upgrader = websocket.Upgrader{
          ReadBufferSize:  1024,
          WriteBufferSize: 1024,
          CheckOrigin:     func(r *http.Request) bool { return true },
      }
      pingPeriod = (pongPeriod * 9) / 10
      pongPeriod = 60 * time.Second
      writeWait  = 10 * time.Second
  )
  
  
  func PingResponse(ws *websocket.Conn) {
      conf := storage.GetConfig()
      defer ws.Close()
      ws.SetReadLimit(512)
      ws.SetReadDeadline(time.Now().Add(pongPeriod))
      ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongPeriod)); return nil })
      for {
          _, _, err := ws.ReadMessage()
          if err != nil {
              if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
                  conf.Log.Debugf(&quot;Websocket Ping Read Failed: %v&quot;, err)
              }
  
              return
          } else {
              conf.Log.Debugf(&quot;Received message from Websocket client&quot;)
          }
      }
  }
  
  func ServeAllUsersWebsocket(datachan chan *[]storage.UserResponse) http.Handler {
      return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
          conf := storage.GetConfig()
          ws, err := upgrader.Upgrade(w, r, nil)
          if err != nil {
              conf.Log.Debugf(&quot;Failed to upgrade data to Websocket: %v&quot;, err)
              return
          }
  
          go allUserWebsocketWriter(ws, datachan)
          go PingResponse(ws)
      })
  }
  
  
  func allUserWebsocketWriter(ws *websocket.Conn, datachan chan *[]storage.UserResponse) {
      conf := storage.GetConfig()
      pingticker := time.NewTicker(pingPeriod)
      defer func() {
          pingticker.Stop()
          ws.Close()
      }()
  
      userresponse, err := conf.Database.GetAllUsers()
      if err != nil {
          conf.Log.Errorf(&quot;Failed to query users from database: %v&quot;, err)
          return
      }
  
      ws.SetWriteDeadline(time.Now().Add(writeWait))
      err = ws.WriteJSON(&amp;userresponse)
      if err != nil {
          conf.Log.Debugf(&quot;Failed to write initial user response: %v&quot;, err)
          return
      }
  
      for {
          select {
          case data := &lt;-datachan:
              ws.SetWriteDeadline(time.Now().Add(writeWait))
              err := ws.WriteJSON(&amp;data)
              if err != nil {
                  conf.Log.Debugf(&quot;Failed to write data to Websocket: %v&quot;, err)
                  return
              }
          case &lt;-pingticker.C:
              ws.SetWriteDeadline(time.Now().Add(writeWait))
              conf.Log.Debugf(&quot;Sending Ping Message to Client&quot;)
              if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
                  conf.Log.Debugf(&quot;Failed to write ping message to Websocket: %v&quot;, err)
                  return
              }
          }
      }
  }
  </code></pre>
  <p>Basically, we are posting the current data to the new Websocket Connection, when it is updated - this does always work. Afterwards, if the database changes, it posts the updated userlist into the channel - the websocket should then post it to the client which updates the list. We are also sending ping messages - which fail (as seen in the log above). The client itself does not log any errors or closes the websocket.</p>