/// <summary>
        /// Connect this Socket.IO instance to a new target (this even works after the initial connect)
        /// </summary>
        /// <param name="targetAddress">The server / IO address to connect to. Has to start with http:// or https:// (substitute ws with http or wss with https): http[s]://<Hostname>[:<Port>][/<path>]</param>
        /// <param name="enableReconnect">Shall we reconnect automatically on an unexpected connection loss?</param>
        /// <param name="authPayload">Null or an instance of SIOAuthPayload to be sent upon connection. Can for example be used to send an authentication token.</param>
        public virtual void Connect(string targetAddress, bool enableReconnect, SIOAuthPayload authPayload)
        {
            if (!targetAddress.StartsWith("http://") && !targetAddress.StartsWith("https://"))
            {
                throw new UriFormatException("Socket.IO Address has to start with http:// or https:// if provided programmatically");
            }

            this.targetAddress       = targetAddress;
            this.enableAutoReconnect = enableReconnect;
            this.authPayload         = authPayload;
        }
Exemple #2
0
        public override void Connect(string targetAddress, bool enableReconnect, SIOAuthPayload authPayload)
        {
            base.Connect(targetAddress, enableReconnect, authPayload);

            string payload = "";

            if (this.authPayload != null)
            {
                payload = this.authPayload.GetPayloadJSON();
            }

            SocketIOManager.LogDebug("Creating and connecting WebGL-Based Socket.IO instance for " + this.GameObjectName);
            CreateSIOInstance(InstanceName, this.GameObjectName, targetAddress, enableReconnect ? 1 : 0, payload);
        }
 /// <summary>
 /// Connect this Socket.IO instance using the component's set configuration but with (new) auth data
 /// </summary>
 /// <param name="authPayload">An instance of SIOAuthPayload to be sent upon (re-)connection. Can for example be used to send an authentication token.</param>
 public virtual void Connect(SIOAuthPayload authPayload)
 {
     Connect(targetAddress, this.enableAutoReconnect, authPayload);
 }
    public override void Connect(string targetAddress, bool enableReconnect, SIOAuthPayload authPayload)
    {
        base.Connect(targetAddress, enableReconnect, authPayload);

        Task.Run(async() =>
        {
            //We need a fresh (uncancelled) source
            cTokenSrc = new CancellationTokenSource();

            if (ReconnectAttempts > 0)
            {
                SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("reconnect_attempt", ReconnectAttempts.ToString()); }));
            }

            //Kill all remaining threads
            if (Socket != null && Socket.State == WebSocketState.Open)
            {
                await Socket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Reconnect required", cTokenSrc.Token);
            }
            //else if (ReconnectAttempts > 0) SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("reconnect_attempt", ReconnectAttempts.ToString()); }));

            lock (Socket)
            {
                Socket = new ClientWebSocket();
            }

            try
            {
                string websocketAddress = "ws" + targetAddress.Substring(4);
                if (targetAddress.IndexOf("/", 8) == -1)
                {
                    websocketAddress += "/socket.io/";
                }
                Uri baseUri = new Uri(websocketAddress);

                SocketIOManager.LogDebug("Connecting to server " + baseUri.Scheme + "://" + baseUri.Host + ":" + baseUri.Port + " on path " + baseUri.AbsolutePath);
                Uri connectTarget = new Uri(baseUri.Scheme + "://" + baseUri.Host + ":" + baseUri.Port + baseUri.AbsolutePath + "?EIO=4&transport=websocket" + (baseUri.Query.Length > 1 ? "&" + baseUri.Query.Substring(1) : ""));
                await Socket.ConnectAsync(connectTarget, CancellationToken.None);
                for (int i = 0; i < 50 && Socket.State != WebSocketState.Open; i++)
                {
                    Thread.Sleep(50);
                }
                if (Socket.State != WebSocketState.Open)
                {
                    //Something went wrong. This should not happen. Stop operation, wait a moment and try again
                    cTokenSrc.Cancel();
                    Thread.Sleep(1500);
                    Connect();
                }
            }
            catch (Exception e)
            {
                if (ReconnectAttempts == 0)
                {
                    SocketIOManager.LogError(InstanceName + ": " + e.GetType().Name + " - " + e.Message + " (" + targetAddress + ")");
                    if (e.GetType().Equals(typeof(WebSocketException)))
                    {
                        SocketIOManager.LogWarning(InstanceName + ": Please make sure that your server supports the 'websocket' transport. Load-Balancers, Reverse Proxies and similar appliances often require special configuration.");
                    }
                    if (e.GetType().Equals(typeof(System.Security.Authentication.AuthenticationException)))
                    {
                        SocketIOManager.LogWarning(InstanceName + ": Please verify that your server is using a valid SSL certificate which is trusted by this client's system CA store");
                    }
                    SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("connect_error", e.GetType().Name + " - " + e.Message); }));
                    //SIODispatcher.Instance?.Enqueue(new Action(() => { RaiseSIOEvent("connect_timeout", null); }));
                }
                else
                {
                    SocketIOManager.LogError(InstanceName + ": " + e.GetType().Name + " - " + e.Message + " (while reconnecting) ");
                    SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("reconnect_error", e.GetType().Name + " - " + e.Message); }));
                }
                Status = SIOStatus.ERROR;

                //Limit the max reconnect attemts
                if (ReconnectAttempts > 150)
                {
                    Status = SIOStatus.ERROR;
                    SIODispatcher.Instance?.Enqueue(new Action(() => { RaiseSIOEvent("reconnect_failed"); }));
                    return;
                }

                //An error occured while connecting, we need to reconnect.
                Thread.Sleep(500 + (ReconnectAttempts++ *1000));
                if (!cTokenSrc.IsCancellationRequested)
                {
                    Connect(authPayload);
                }
                return;
            }

            try
            {
                if (WebSocketReaderThread == null || !WebSocketReaderThread.IsAlive)
                {
                    WebSocketReaderThread = new Thread(new ThreadStart(SIOSocketReader));
                    WebSocketReaderThread.Start();
                }

                if (WebSocketWriterThread == null || !WebSocketWriterThread.IsAlive)
                {
                    WebSocketWriterThread = new Thread(new ThreadStart(SIOSocketWriter));
                    WebSocketWriterThread.Start();
                }

                if (WatchdogThread == null || !WatchdogThread.IsAlive)
                {
                    WatchdogThread = new Thread(new ThreadStart(SIOSocketWatchdog));
                    WatchdogThread.Start();
                }
            }
            catch (Exception e)
            {
                SocketIOManager.LogError("Exception while starting threads on " + InstanceName + ": " + e.ToString());
                Status = SIOStatus.ERROR;
                return;
            }
        });
    }
Exemple #5
0
    // Start is called before the first frame update
    void Start()
    {
        //sioCom is assigned via inspector so no need to initialize it.
        //We just fetch the actual Socket.IO instance using its integrated Instance handle and subscribe to the connect event
        sioCom.Instance.On("connect", (string data) => {
            Debug.Log("LOCAL: Hey, we are connected!");
            uiStatus.text = "Socket.IO Connected. Doing work...";

            //NOTE: All those emitted and received events (except connect and disconnect) are made to showcase how this asset works. The technical handshake is done automatically.

            //First of all we knock at the servers door
            //EXAMPLE 1: Sending an event without payload data
            sioCom.Instance.Emit("KnockKnock");
        });

        //The server will respont to our knocking by askin who we are:
        //EXAMPLE 2: Listening for an event without payload
        sioCom.Instance.On("WhosThere", (string payload) =>
        {
            //We will always receive a payload object as Socket.IO does not distinguish. In case the server sent nothing (as it will do in this example) the object will be null.
            if (payload == null)
            {
                Debug.Log("RECEIVED a WhosThere event without payload data just as expected.");
            }

            //As the server just asked for who we are, let's be polite and answer him.
            //EXAMPLE 3: Sending an event with payload data
            ItsMeData me = new ItsMeData()
            {
                version = Application.unityVersion
            };
            sioCom.Instance.Emit("ItsMe", JsonUtility.ToJson(me), false); //Please note the third parameter which is semi-required if JSON.Net is not installed
        });


        //The server will now receive our event and parse the data we sent. Then it will answer with two events.
        //EXAMPLE 4: Listening for an event with plain text payload
        sioCom.Instance.On("Welcome", (string payload) =>
        {
            Debug.Log("SERVER: " + payload);
            uiGreeting.text = payload;
        });


        //EXAMPLE 5: Listening for an event with JSON Object payload
        sioCom.Instance.On("TechData", (string payload) =>
        {
            ServerTechData srv = JsonUtility.FromJson <ServerTechData>(payload);
            Debug.Log("Received the POD name from the server. Upadting UI. Oh! It's " + srv.timestamp + " by the way.");
            uiPodName.text = "I talked to " + srv.podName;

            //Let's ask for random numbers (example 6 below)
            sioCom.Instance.Emit("SendNumbers");
        });


        //EXAMPLE 6: Listening for an event with JSON Array payload
        sioCom.Instance.On("RandomNumbers", (string payload) =>
        {
            Debug.Log("We received the following JSON payload from the server for example 6: " + payload);

            //Please note that unity's JsonUtility is not able to parse JSON arrays. You would need JSON.Net for this task.
            //This is how it works - if Json.NET is installed:
#if HAS_JSON_NET
            int[] numbers = JsonConvert.DeserializeObject <int[]>(payload);
            Debug.Log("Thanks to Json.NET we were able to decode the numbers: " + string.Join(", ", numbers));
#endif

            //Send a goodbye to the server
            sioCom.Instance.Emit("Goodbye", "Thanks for talking to me!", true); //Please note the third parameter which is semi-required if JSON.Net is not installed
        });


        //When the conversation is done, the server will close our connection after we said Goodbye
        sioCom.Instance.On("disconnect", (string payload) => {
            if (payload.Equals("io server disconnect"))
            {
                Debug.Log("Disconnected from server.");
                uiStatus.text = "Finished. Server closed connection.";
            }
            else
            {
                Debug.LogWarning("We have been unexpecteldy disconnected. This will cause an automatic reconnect. Reason: " + payload);
            }
        });


        //We are now ready to actually connect
        //The simnple way will use the parameters set in the inspector (or with a former call to Connect(...)):
        //sioCom.Instance.Connect();

        //For this example we will also show how to transmit a token or other data for authentication purposes:
        //PLEASE NOTE: You can only transmit primitives using the "authPayload". int, string, float...
        SIOAuthPayload auth = new SIOAuthPayload();
        auth.AddElement("id", 1234);                       //The server will access this using socket.handshake.auth.id
        auth.AddElement("token", "UnitySample-abc123zyx"); //The server will access this using socket.handshake.auth.token
        //You could again use the component config for the target by using
        //sioCom.Instance.Connect(auth);

        //But the following command shows how you can programmatically connect to any server at any given time - in this case including our previously set auth information
        sioCom.Instance.Connect("https://sio-v4-example.unityassets.i01.clu.firesplash.de", false, auth);
    }