Search Unity

Unity WebGL using Websockets can't get message from server

Discussion in 'Web' started by macepok, Nov 8, 2020.

  1. macepok

    macepok

    Joined:
    Apr 18, 2019
    Posts:
    11
    I 'am following this guide to build a WebGL project with WebSockets.

    https://medium.com/@hacj/unity-webgl-and-websockets-a-guide-42f3e8f0db34

    In Editor, it is worked. The client can send and receive message from server. However, build on WebGL is not working. The client can send message to server but can't receive message from server. Any step I miss? Or anyone can help me? Thanks.

    Sever code:
    Code (CSharp):
    1. using System;
    2. using WebSocketSharp;
    3. using WebSocketSharp.Server;
    4. using System.Security.Cryptography.X509Certificates;
    5.  
    6. namespace Example
    7. {
    8.    public class Echo : WebSocketBehavior
    9.    {
    10.        protected override void OnMessage(MessageEventArgs e)
    11.        {
    12.            var msg = System.Text.Encoding.UTF8.GetString(e.RawData);
    13.            Console.WriteLine("Got Message: " + msg);
    14.            Send(msg);
    15.        }
    16.    }
    17.  
    18.   public class Program
    19.   {
    20.    public static void Main (string[] args)
    21.    {
    22.      var wssv = new WebSocketServer (9000, true);
    23.  
    24.      wssv.SslConfiguration.ServerCertificate =
    25.      new X509Certificate2 ("cert.pfx");
    26.  
    27.      wssv.AddWebSocketService<Echo> ("/echo");
    28.      wssv.Start ();
    29.      Console.Read();
    30.      wssv.Stop ();
    31.    }
    32.   }
    33. }
    Client code in Unity:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Text;
    4. using UnityEngine;
    5.  
    6. // Use plugin namespace
    7. using HybridWebSocket;
    8.  
    9. public class WebSocketDemo : MonoBehaviour {
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.  
    14.         // Create WebSocket instance
    15.         WebSocket ws = WebSocketFactory.CreateInstance("ws://localhost:9000/echo");
    16.  
    17.         // Add OnOpen event listener
    18.         ws.OnOpen += () =>
    19.         {
    20.             Debug.Log("WS connected!");
    21.             Debug.Log("WS state: " + ws.GetState().ToString());
    22.  
    23.             ws.Send(Encoding.UTF8.GetBytes("Hello from Unity 3D!"));
    24.         };
    25.  
    26.         // Add OnMessage event listener
    27.         ws.OnMessage += (byte[] msg) =>
    28.         {
    29.             Debug.Log("WS received message: " + Encoding.UTF8.GetString(msg));
    30.  
    31.             ws.Close();
    32.         };
    33.  
    34.         // Add OnError event listener
    35.         ws.OnError += (string errMsg) =>
    36.         {
    37.             Debug.Log("WS error: " + errMsg);
    38.         };
    39.  
    40.         // Add OnClose event listener
    41.         ws.OnClose += (WebSocketCloseCode code) =>
    42.         {
    43.             Debug.Log("WS closed with code: " + code.ToString());
    44.         };
    45.  
    46.         // Connect to the server
    47.         ws.Connect();
    48.  
    49.     }
    50.    
    51.     // Update is called once per frame
    52.     void Update () {
    53.        
    54.     }
    55. }
     
  2. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
  3. theovenigma

    theovenigma

    Joined:
    Jun 22, 2021
    Posts:
    3
    Have you found any solution to this? I'm having the same problem
     
  4. NeoReelMac

    NeoReelMac

    Joined:
    Feb 3, 2020
    Posts:
    15
    The solution is that in WebSocket.jslib, in the instance.ws.onmessage = function(ev), the if statement
    if (ev.data instanceof ArrayBuffer)
    only reats ArrayBuffers (binary data), but you are sending a string. So you need to add
    else if(typeof ev.data === "string")
    and then send the webSocketState.onMessage with that string as the argument.
    I have not yet been able to convert ev.data to a string an pass it to onMessage, but I have to continue searching... If anyone know, please help. This is what I have:

    Code (CSharp):
    1.        else if(typeof ev.data === "string")
    2.            {
    3.                var msgBytes = lengthBytesUTF8(ev.data) + 1;
    4.                var msgBuffer = _malloc(msgBytes);
    5.                stringToUTF8(ev.data, msgBuffer, msgBytes);
    6.                try {
    7.                    Module['dynCall_viii'](webSocketState.onMessage, instanceId, msgBuffer, msgBytes);
    8.                } finally {
    9.                    _free(buffer);
    10.                }
    11.            }
     
  5. NeoReelMac

    NeoReelMac

    Joined:
    Feb 3, 2020
    Posts:
    15
    I ended up changing all the OnMessage functions to be like the OnError function, which takes a string instead of bytes[]