websocket-sharp icon indicating copy to clipboard operation
websocket-sharp copied to clipboard

Websocket connection doesn't work after reload on OSX Web Player

Open ssfrr opened this issue 11 years ago • 4 comments

In our application, we're connecting to a server via web sockets to listen for new data. Everything works fine on the desktop builds, and the web player on windows, and on OSX with a freshly-opened browser. After a browser reload, or closing and re-opening a tab, we get errors receiving websocket messages. It looks like we're hitting a known issue with Unity and the various Async IO methods in the web player, where Async processes don't get closed properly when the player is stopped.

Here is an informative forum post describing the issue. In this case the resolution was to abandon the Async methods and spawn a separate thread manually that does blocking reads. http://forum.unity3d.com/threads/socket-wont-stay-connected-after-reloading-webplayer.102776/

In our case specifically the exception was "An exception has occurred while receiving a message." That error was coming from ParseAsync which was throwing the exception "The header part of a frame cannot be read from the data source." because header.Length was zero. This seems to match up with the error reported above, where async reads were returning zero bytes after a reload.

As this seems to be an open and long-standing issue in Unity, would it be hard to refactor out the Async methods? I'm not sure if there's another workaround to get things working in OSX Web Player after a refresh (if you have one we're all ears).

Thanks.

ssfrr avatar Jun 13 '14 21:06 ssfrr

Thanks for input, i've read that forum post.

So, does the following work after that reloading? Could you try?

To replace the startReceiving () method with the below, in WebSocket.cs:

    private void startReceiving ()
    {
      if (_messageEventQueue.Count > 0)
        _messageEventQueue.Clear ();

      _exitReceiving = new AutoResetEvent (false);
      _receivePong = new AutoResetEvent (false);

      Action receive = null;
      receive = () => ThreadPool.QueueUserWorkItem (
        state => {
          try {
            var frame = _stream.ReadFrame ();
            if (acceptFrame (frame) && _readyState != WebSocketState.Closed) {
              receive ();

              if (!frame.IsData)
                return;

              lock (_forEvent) {
                try {
                  var e = dequeueFromMessageEventQueue ();
                  if (e != null && _readyState == WebSocketState.Open)
                    OnMessage.Emit (this, e);
                }
                catch (Exception ex) {
                  acceptException (ex, "An exception has occurred while OnMessage.");
                }
              }
            }
            else if (_exitReceiving != null) {
              _exitReceiving.Set ();
            }
          }
          catch (Exception ex) {
            acceptException (ex, "An exception has occurred while receiving a message.");
          }
        }
      );

      receive ();
    }

sta avatar Jun 14 '14 18:06 sta

Thanks for the quick response and patch. I'm testing it out now and should have results shortly.

ssfrr avatar Jun 14 '14 18:06 ssfrr

This patch appears to resolve the issue! Thanks!

I just submitted another issue (#52) with all the errors that came up trying to build against the latest master (I had been using an older version). Here were my steps:

  1. did a fresh checkout
  2. copied the websocket-sharp folder into my Assets/Plugins folder
  3. made the changes necessary to get it to build
  4. Tested to verify that the issue after reloading was still present in current master (it was)
  5. replaced the startReceiving() method with the code from above
  6. Tested to verify the problem was resolved.

Thanks for the quick fix!

ssfrr avatar Jun 14 '14 19:06 ssfrr

Thanks for input, i've read that forum post.

So, does the following work after that reloading? Could you try?

To replace the startReceiving () method with the below, in WebSocket.cs:

    private void startReceiving ()
    {
      if (_messageEventQueue.Count > 0)
        _messageEventQueue.Clear ();

      _exitReceiving = new AutoResetEvent (false);
      _receivePong = new AutoResetEvent (false);

      Action receive = null;
      receive = () => ThreadPool.QueueUserWorkItem (
        state => {
          try {
            var frame = _stream.ReadFrame ();
            if (acceptFrame (frame) && _readyState != WebSocketState.Closed) {
              receive ();

              if (!frame.IsData)
                return;

              lock (_forEvent) {
                try {
                  var e = dequeueFromMessageEventQueue ();
                  if (e != null && _readyState == WebSocketState.Open)
                    OnMessage.Emit (this, e);
                }
                catch (Exception ex) {
                  acceptException (ex, "An exception has occurred while OnMessage.");
                }
              }
            }
            else if (_exitReceiving != null) {
              _exitReceiving.Set ();
            }
          }
          catch (Exception ex) {
            acceptException (ex, "An exception has occurred while receiving a message.");
          }
        }
      );

      receive ();
    }

Hi, I'm experiencing this exact same issue. But the code has changed so much that this workaround doesn't work. Could you please update the workaround?

253153 avatar Jun 29 '22 17:06 253153