Gameobject not being set active in 'catch'. I've checked everything - c#

Here is what I'm trying to do:
Trying to check if there's internet connection or no. If there is no internet connection, I want to set active a panel showing 'no internet connection'.
I dragged the panel to the inspector. The script which sets this panel active is on a gameobject which is active in hierarchy.
Here is the code:
public GameObject NoInternetConnectionPanel;
private void Start()
{
//Check Internet Connection
InvokeRepeating("CheckInternetConnection", 0f, 1f);
}
private void CheckInternetConnection()
{
var request = WebRequest.Create("http://google.com");
request.Method = "HEAD";
request.BeginGetResponse(result =>
{
try
{
using (var response = request.EndGetResponse(result) as HttpWebResponse)
{
if (response.StatusCode == HttpStatusCode.OK)
{
Debug.Log("Internet connection available");
}
/*else
{
Debug.Log("No internet connection");
}*/
}
}
catch (WebException ex)
{
Debug.Log("No internet connection");
NoInternetConnectionPanel.SetActive(true);
}
}, null);
StartCoroutine(WaitAndCheck());
}
private IEnumerator WaitAndCheck()
{
yield return new WaitForSeconds(1f);
}
The debug log message "no internet connection" is being shown in console. But the 'NoInternetConnectionPanel.SetActive(true)' is not working.
What could be the issue?

That's most probably because it is being executed on another any thread which is not supported by most of the Unity API. In general you shouldn't be using WebRequest at all but rather use UnityWebRequest in a Coroutine.
Also not btw that your WaitAndCheck routine doesn't do anything at all.
I would rather use something like e.g.
public GameObject NoInternetConnectionPanel;
private IEnumerator Start()
{
while(true)
{
yield return CheckInternetConnection();
yield return new WaitForSeconds(1f);
}
}
private IEnumerator CheckInternetConnection()
{
using(var request = UnityWebRequest.Head("http://google.com"))
{
yield return request.SendWebRequest();
var connection = request.result == UnityWebRequest.Result.Success;
NoInternetConnectionPanel.SetActive(! connection);
if(connection)
{
Debug.Log("Internet connection available");
}
else
{
Debug.LogWarning("No internet connection");
}
}
}
Instead of using a we request at all you can also use a simple Ping which is often used with e.g. 8.8.8.8, Google's global DNS server.
private IEnumerator CheckInternetConnection()
{
var ping = new Ping("8.8.8.8");
var maxPingTime = 1f; // maximum time to wait before declaring the ping as failed
var connection = false;
for(var timePassed = 0f; timePassed <= maxPingTime; timePassed += Time.deltaTime)
{
if(ping.isDone)
{
connection = true;
break;
}
}
NoInternetConnectionPanel.SetActive(! connection);
if(connection)
{
Debug.Log("Internet connection available");
}
else
{
Debug.LogWarning("No internet connection");
}
}

Related

WWW freezing when there is no internet

I am writing a simple code in Unity, to check if I am able to reach a website through my app. This is the code I have written:
IEnumerator CheckInternetPing()
{
WWW wwwInternet = new WWW("http://google.com");
yield return wwwInternet;
if (wwwInternet.bytesDownloaded == 0)
{
//yield return new WaitForSeconds(1f);
Debug.Log("Not Connected to Internet");
}
else
{
Debug.Log("Connected to Internet");
internetMenu.SetActive(false);
}
}
I have found a bug where if I run this with my Internet on, it shows "Connected", but when I switch the Internet off and run the app immediately after, it logs nothing. It shows "Not Connected" only if I restart the app another time.
Does anyone know why it logs nothing during the first time? Thanks
This is a bug with the WWW class and has been here for a long time. The behavior is probably different every device. It used to freeze on the Editor if Wifi is disabled. A quick test showed that this bug has not been fixed.
You need to use HttpWebRequest instead of WWW.
In the example below, Thread is used to avoid the request blocking Unity program and UnityThread is used to make callback into Unity main Thread when the request is done. Get UnityThread from this post.
void Awake()
{
//Enable Callback on the main Thread
UnityThread.initUnityThread();
}
void isOnline(Action<bool> online)
{
bool success = true;
//Use ThreadPool to avoid freezing
ThreadPool.QueueUserWorkItem(delegate
{
try
{
int timeout = 2000;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://google.com");
request.Method = "GET";
request.Timeout = timeout;
request.KeepAlive = false;
request.ServicePoint.Expect100Continue = false;
request.ServicePoint.MaxIdleTime = timeout;
//Make sure Google don't reject you when called on mobile device (Android)
request.changeSysTemHeader("User-Agent", "Mozilla / 5.0(Windows NT 10.0; WOW64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 55.0.2883.87 Safari / 537.36");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response == null)
{
success = false;
}
if (response != null && response.StatusCode != HttpStatusCode.OK)
{
success = false;
}
}
catch (Exception)
{
success = false;
}
//Do the callback in the main Thread
UnityThread.executeInUpdate(() =>
{
if (online != null)
online(success);
});
});
}
You need the extension class for the changeSysTemHeader function that allows the "User-Agent" header to be changed:
public static class ExtensionMethods
{
public static void changeSysTemHeader(this HttpWebRequest request, string key, string value)
{
WebHeaderCollection wHeader = new WebHeaderCollection();
wHeader[key] = value;
FieldInfo fildInfo = request.GetType().GetField("webHeaders",
System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.GetField);
fildInfo.SetValue(request, wHeader);
}
}
It is really simple to use:
void Start()
{
isOnline((online) =>
{
if (online)
{
Debug.Log("Connected to Internet");
//internetMenu.SetActive(false);
}
else
{
Debug.Log("Not Connected to Internet");
}
});
}

Determine if the newly connected player is a client or the server player(host) and remove a msg on the server

I want to determine if the newly connected player is a client and on server player(host) remove a msg. In UNET i want there to be two players over LAN. The first player is the server player and then their opponent connects.
The player searches for a LAN match to join like so:
public void StartPlayerClient() {
Debug.Log ("client set up");
discovery.Initialize ();
discovery.StartAsClient ();
searching = true;
}
Once a match is found it receives displays it like this:
void Update() {
if (searching) {
if (discovery.broadcastsReceived != null) {
foreach (var addr in discovery.broadcastsReceived.Keys) {
var value = discovery.broadcastsReceived [addr];
//instantiate ui button to connect...
GameObject ui = Instantiate (GameController.instance.multiplayerMatchConnect) as GameObject;
ui.GetComponent<ConnectToMatch> ().Initialize (value);
ui.transform.SetParent (GameController.instance.matchListParent.transform, false);
}
if (discovery.broadcastsReceived.Keys.Count > 0) {
searching = false;
}
} else {
searching = false;
}
}
}
then the player is able to connect by clicking the button that was just instantiated like so:
public void Initialize(NetworkBroadcastResult value) {
res = value;
GetComponent<Button> ().onClick.AddListener (Connect);
}
void Connect() {
Debug.Log ("connecting...");
string dataString = BytesToString (res.broadcastData);
var items = dataString.Split(':');
if (items.Length == 3 && items[0] == "NetworkManager") {
if (NetworkManager.singleton != null && NetworkManager.singleton.client == null) {
NetworkManager.singleton.networkAddress = items[1];
NetworkManager.singleton.networkPort = Convert.ToInt32(items[2]);
NetworkManager.singleton.StartClient();
}
}
}
Now that all works fine, these are the troublesome parts:
//called on the server when client connects
public override void OnServerConnect(NetworkConnection conn) {
if (NetworkServer.connections.Count > 1) {
GameController.instance.pnlWaitingForOtherPlayer.SetActive (false);
Debug.Log ("player connected");
GameController.instance.pnlMatchList.SetActive (false);
GameController.instance.pnlJoinCreateMenu.SetActive (false);
}
}
on the server client it will say "Waiting for other player" before they connect.. when they do i want the msg to disappear for the server player, this is how im trying to do it and it does not work.
//called on the client when connects to the server
public override void OnClientConnect(NetworkConnection conn) {
if (!discovery.isServer) {
GameController.instance.pnlMatchList.SetActive (false);
Debug.Log("you connected");
}
}

UWP MediaPlayer stops playing sounds

I'm using the MediaPlayer class (https://learn.microsoft.com/en-us/windows/uwp/controls-and-patterns/media-playback) to play sounds in my UWP Project. This all works fine at the beginning but suddenly the Play() call starts "playing" the sound (e.g. the state of the PlaybackSession is "Playing") but there is no sound output...
Dictionary<string, MediaPlayer> Effects = new Dictionary<string, MediaPlayer>();
public async Task LoadEffects()
{
Effects?.Clear();
StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("sounds");
foreach (var effect in await folder.GetFilesAsync())
{
MediaPlayer snd = new MediaPlayer();
snd.AutoPlay = false;
snd.Source = MediaSource.CreateFromStorageFile(effect);
snd.RealTimePlayback = true;
snd.AudioCategory = MediaPlayerAudioCategory.GameMedia;
Effects.Add(effect.DisplayName, snd);
}
IsLoaded = true;
}
public void StartPlaying(string name, float volume = 1.0f, bool force = false)
{
lock (_instance)
{
if (Effects.ContainsKey(name))
{
//if force is true, force the sound to stop and play again otherwise just exit
if (Effects[name].PlaybackSession.PlaybackState == MediaPlaybackState.Playing && !force)
{
return;
}
Effects[name].Pause();
Task.Delay(100).ContinueWith((res) =>
{
Effects[name].Volume = volume;
Effects[name].PlaybackSession.Position = TimeSpan.Zero;
Effects[name].IsLoopingEnabled = true;
Effects[name].Play();
});
}
}
}
public void StopPlaying(string name)
{
lock (_instance)
{
try
{
//if nothing is playing just return
if (Effects[name].PlaybackSession.PlaybackState != MediaPlaybackState.Playing) return;
}
catch(Exception ex)
{
//weird error happens sometimes, catch it and just return
return;
}
if (Effects.ContainsKey(name))
{
Debug.WriteLine($"Stopping {name} now; state before: {Effects[name].PlaybackSession.PlaybackState.ToString()}");
Effects[name].IsLoopingEnabled = false;
Effects[name].Pause();
Effects[name].PlaybackSession.Position = TimeSpan.Zero;
}
}
}
I noticed that it seems to happen more frequently when I'm not using the Task.Delay().
The lock is used, since I have a singleton class.

Reconnecting to socket.io server takes long time after receiving messages using SocketIoClientDotNet

I'm developing a plugin for Grasshopper for Rhino which uses a .NET framework with C# and I have a problem when reconnecting to a socket.io 1.4.5 server. I'm using SocketIoClientDotNet 0.9.13 to connect to a server and it works fine if I just want to connect/disconnect to a server but I have a problem reconnecting to a server after I received a message using an event taking a lot of time to reconnect.
Depends on the number of messages I received by the event during the connection, after I close and make a new connection it takes more than a minute (sometimes more than 10 mins if there are a lot of messages received) for the new connection.
Could anybody tell what is going wrong?
The code is written as follows:
Quobject.SocketIoClientDotNet.Client.Socket socket;
private System.Threading.ManualResetEvent manualResetEvent = null;
private bool currentState = false;
public object output = null;
public bool connected = false;
private Quobject.SocketIoClientDotNet.Client.IO.Options CreateOptions()
{
Quobject.SocketIoClientDotNet.Client.IO.Options op = new Quobject.SocketIoClientDotNet.Client.IO.Options();
op.AutoConnect = true;
op.Reconnection = true;
op.ReconnectionAttempts = 5;
op.ReconnectionDelay = 5;
op.Timeout = 20;
op.Secure = true;
op.ForceNew = true;
op.Multiplex = true;
return op;
}
private void ConnectToSocket(bool b, string address){
if(currentState != b){
if(b && !connected){
manualResetEvent = new System.Threading.ManualResetEvent(false);
var options = CreateOptions();
socket = IO.Socket(address, options);
socket.On(Quobject.SocketIoClientDotNet.Client.Socket.EVENT_CONNECT, () =>
{
connected = true;
Print("connected");
manualResetEvent.Set();
});
socket.On("slider_message", (data) =>
{
if(data != null){
var jobject = data as JToken;
try{
var sliderValue = jobject.Value<string>("slider");
output = sliderValue;
}catch{
}
}
manualResetEvent.Set();
});
socket.On(Quobject.SocketIoClientDotNet.Client.Socket.EVENT_DISCONNECT, () =>
{
connected = false;
Print("disconnected");
manualResetEvent.Set();
});
Print("connecting...");
manualResetEvent.WaitOne();
}else{
if(socket != null & connected){
manualResetEvent = new System.Threading.ManualResetEvent(false);
Print("disconnecting...");
socket.Close();
manualResetEvent.WaitOne();
socket = null;
}
}
}
currentState = b;
}

How to determine if the tcp is connected or not?

I have tcpclient object and i want to determine if it's connected or not.
i use connected property of tcpclient but it returns the state of last operation. so its not useful.
then i use this code :
bool flag;
flag = (tcp.Client.Poll(10000, SelectMode.SelectWrite));
and
if( tcp.Client.Poll( 0, SelectMode.SelectRead ) )
{
byte[] buff = new byte[1];
if( tcp.Client.Receive( buff, SocketFlags.Peek ) == 0 )
{
flag = false;
}
}
but it does not work properly.
Any idea?
this is my code in server side :
private ArrayList _ClientList = new ArrayList();
public ClsServer(int port)
{
_TCPListener = new TcpListener(IPAddress.Any, port);
_TCPListener.Start();
Thread ListenThread = new Thread(new ThreadStart(ListenForClients));
ListenThread.IsBackground = true;
ListenThread.Start();
}
private void ListenForClients()
{
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this._TCPListener.AcceptTcpClient();
client.ReceiveTimeout = 0;
//create a thread to handle communication with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.IsBackground = true;
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
try
{
TcpClient tcpClient = (TcpClient)client;
AddObject(tcpclient);
int bytesRead;
string message = "";
byte[] RecievedPack = new byte[1024 * 1000];
NetworkStream clientStream = tcpClient.GetStream();
while (true)
{
bytesRead = 0;
try
{
////blocks until a client sends a message
bytesRead = clientStream.Read(RecievedPack, 0, RecievedPack.Length);
int Len = BitConverter.ToInt32(RecievedPack, 0);
message = UTF8Encoding.UTF8.GetString(RecievedPack, 0, Len);
}
catch (Exception er)
{
//When Client is disconnected
if (er.GetType() == typeof(IOException))
{
RemoveObject(client);
break;
}
}
//message has successfully been received
// do something
}
RemoveObject(client);
}
catch(Exception e)
{
// RemoveObject(client);
}
}
private void AddObject(object obj)
{
int totalcount, index;
totalcount = _ClientList.Count;
index = 0;
while (index < totalcount)
{
TcpClient alcobj = (TcpClient)_ClientList[index];
try
{
if (IPAddress.Equals(((IPEndPoint)alcobj.Client.RemoteEndPoint).Address,
((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address))
{
_ClientList.Remove(alcobj);
break;
}
index++;
}
catch (Exception er)
{
if (er.GetType() == typeof(ObjectDisposedException))
RemoveObject(alcobj);
}
finally
{
totalcount = _ClientList.Count;
}
}
_ClientList.Add(obj);
}
private void RemoveObject(object obj)
{
if (_ClientList.IndexOf(obj) > -1)
{
_ClientList.Remove(obj);
SendClientState(IP, false);
}
}
and this is the client side :
public bool IsConnected
{
try
{
if (_TcpClient != null && _TcpClient.Client != null && _TcpClient.Client.Connected)
{
// Detect if client disconnected
if (_TcpClient.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (_TcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
{
// Client disconnected
return false;
}
else
{
return true;
}
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
private void clsClient()
{
if(!IsConnected())
{
Connecttoserver()
}
}
private void ConnectToServer()
{
try
{
NetworkStream _NetworkStream = _TcpClient.GetStream();
byte[] _RecievedPack = new byte[1024 * 1000];
string _Message = string.Empty;
int _BytesRead;
int _Length;
while (true)
{
_BytesRead = _NetworkStream.Read(_RecievedPack, 0, _RecievedPack.Length);
_Length = BitConverter.ToInt32(_RecievedPack, 0);
_Message = UTF8Encoding.UTF8.GetString(_RecievedPack, 4, _Length);
if (_BytesRead != 0)
{
if (OnReceive != null)
// do something
_NetworkStream.Flush();
}
}
}
catch (Exception exp)
{
// do something
}
}
in client side, IsConnected() always return false and try to connecttoserver, so the server listener always try to add the client in a list
Use this code instead, I have tested it and using it in real production software:
public bool IsConnected
{
get
{
try
{
if (_tcpClient != null && _tcpClient.Client != null && _tcpClient.Client.Connected)
{
/* pear to the documentation on Poll:
* When passing SelectMode.SelectRead as a parameter to the Poll method it will return
* -either- true if Socket.Listen(Int32) has been called and a connection is pending;
* -or- true if data is available for reading;
* -or- true if the connection has been closed, reset, or terminated;
* otherwise, returns false
*/
// Detect if client disconnected
if (_tcpClient.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (_tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
{
// Client disconnected
return false;
}
else
{
return true;
}
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
}
Edit: However you can't rely on just checking the connection and if true proceed, because it returning the status of connection at time this property executed, for instance after you check IsConnected and it returns true, and while you are in the middle of communication, the connection maybe lost there! we just use it in the first place to reduce the probability of failure, So you have to wrap the whole communication in a try/catch and expect the connection to be lost at any time!
I suggest not relaying on such methods.
For my opinion, the best way is to implement some kind of keep-alive mechanism.
Every X seconds, send a small message and wait for an answer.
You're probably disconnected when:
1. You catch an exception when trying to send a keep-alive message (if you're the client side).
2. You don't get a keep-alive message/response for some period of time.
I also suggest not to count on the built-in TCP keep-alive, I found it very not-reliable.
Updated: Found a nice post for this matter: Post
The only way to know whether or not the other end of a socket connection is still connected is by catching the result of a read or write operation or possibly catching an exception.
For more information please refer to this StackOverflow question:
Instantly detect client disconnection from server socket
Here is a small snippet of code that is simply using a Socket in non-blocking mode and connected to a server.
try
{
bytesRead = nambSok.Receive(message, 4096, SocketFlags.None);
}
catch (SocketException e)
{
//a socket error has occured
switch (e.SocketErrorCode)
{
case System.Net.Sockets.SocketError.TimedOut:
case System.Net.Sockets.SocketError.WouldBlock:
if (doDisconnect == false)
{
continue;
}
break;
case System.Net.Sockets.SocketError.ConnectionReset:
case System.Net.Sockets.SocketError.ConnectionAborted:
isConnected = false;
break;
}
}
if (bytesRead > 0)
{
/* do something with data */
}
The "keep-alive" method Lior Ohana proposed is also a great idea. Force each client to "check in" every X seconds. The client can detect the server is gone if an exception occurs on the write, and the server knows the client has gone away if a "keep-alive" message hasn't been received in X seconds.
I agree with Lior Ohana because I had this problem with remote devices that were used GPRS Tcp connection. when device is turn off or disconnected, it did not alert to the sever. There for I used this code: I send Specific time to the clients
void AnalyzeForHandShaking(Socket socketin, string Message)
{
Socket handler = socketin;
try
{
Message = Message.Trim();
if (!string.IsNullOrEmpty(Message.Trim()))
// if (Message.Equals("~"))
{
// string Serial = getSerialFromSocket(socketin).Trim();
DateTime dt = DateTime.Now;
if (handler!=null)
//if there is serial in hastable
if (!arrIPTimeHandShaking.ContainsKey(handler))
{
arrIPTimeHandShaking.Add(handler, dt);
}
else
{
arrIPTimeHandShaking[handler] = dt;
}
}
}
catch
{
}
}

Categories

Resources