Method in event handlers are not called in SignalR after some time - signalr

On starting, the application with SignalR 2 implementation works as expected. But after sometime (it can be after 5 minutes or 30 minutes or 10 minutes), the events are not called anymore. But the Server and Client are still connected. I know it is connected because it the trace level of the client for SignalR, it can still get the commands coming from the Server.
But my messages from my client is still being received by the server and its action executed so I know that the Server - Client connection is still good.
Also, I know that it is still connected because I always check the status of the connection.
This is how I implement the SignalR
public void ConnectAsync()
{
WriteToLogs("Connecting to Server...");
var dic = new Dictionary<string, string> { { "UserName", _signalrSettings.ApplicationName } };
_hubConnection?.Dispose();
_hubConnection = new HubConnection(_signalrSettings.ServerUri, dic);
_hubConnection.StateChanged += Connection_StateChanged;
_hubProxy = _hubConnection.CreateHubProxy(_signalrSettings.HubProxy);
try
{
_hubProxy.On<string, string>("Initial", (a, b) => Initial());
_hubConnection.Start().ContinueWith((s) =>
{
if (s.IsCompleted)
{
_isCompleted = true;
}
else if (s.IsCanceled)
{
_isCompleted = false;
}
else if (s.IsFaulted)
{
_isCompleted = false;
}
_hubProxy.On<string, string>("NewMessage", (userName, message) => NewMessage(userName, message)); // THE "NewMessage" is not fired after some time.
WriteToLogs( $#"Connection status is {_hubConnection.State}");
}).Wait();
}
catch (Exception e)
{
var trace = new StackTrace(e, true);
var reflectedType = trace.GetFrame(0).GetMethod().ReflectedType;
if (reflectedType != null)
{
_messageOperation.WriteErrors($#"Error {e.StackTrace} at {trace}");
}
}
}

Related

Mosquitto client consuming is slowing down and data gap increasing

In a system with multiple devices, diagnostic data is published to separate topics for each device to Mosquitto Broker. A client application tries to consume data by subscribing to these topics separately for each device. The client receives 5 or 6 record per device per minute.
My problem is, after worker application started, the data received from Mosquitto Boroker starts to have delays on the client side. These delays start from 1 second, as time progresses, it lags behind by 1 day and 2 days during the time it is on. After stopping borker, the client continues to consume data.
Any ideas on what causes these delays?
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
string dataHost = _configuration.GetValue<string>("DataHost");
mqttClient = new MqttClient(dataHost);
mqttClient.MqttMsgPublishReceived += MqttClient_MqttMsgPublishReceived;
var list = _configuration.GetValue<string>("DeviceList").Split(',').ToList();
foreach (var deviceId in list)
{
mqttClient.Subscribe(
new string[] { $"{deviceId}/#" },
new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
}
mqttClient.ConnectionClosed += MqttClient_ConnectionClosed;
mqttClient.Connect("client", "username", "pass", false, 10);
}
private void MqttClient_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
try
{
var message = Encoding.UTF8.GetString(e.Message);
var messageArray = e.Topic.Split('/');
if (IsValidJson(message))
{
ItemValue itemValue = JsonConvert.DeserializeObject<ItemValue>(message);
_diagnosticRepository.InsertAsync(new DiagnosticDTO
{
value = messageArray[4].ToString(),
message = message,
messageTime = DateTime.Now,
deviceTime = itemValue.datetime,
sequenceNo = itemValue.sequenceNo,
});
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message, "Consumer Insert Error");
}

Xamarin Forms iOS will not fully connect to Wifi Access Point that has no internet access

I have a Xamarin forms application. The application programmatically connects to a an access to point to communicate via sockets with a host machine connected to that same access point. The access point is not required to have internet access. When testing my code in iOS - I get a socket error stating that the 'Destination is unreachable'. However, if I go to settings and click on the wifi connection I want to use - I am taken to the login page for the access point. If I click cancel I get the option to 'Use without Internet'. If I select that option, then go back to my application, I am able to connect to the host. Is there a way to programmatically tell iOS to use the connecting even though it does not have internet? I looked at the Zone property but that is read only. Here is the code I am using. Any assistance would be appreciated.
public async Task<WifiConfiguredEventArgs> ConnectToWifi()
{
try
{
var tobj_WifiManager = new NEHotspotConfigurationManager();
var tobj_SSIDs = await tobj_WifiManager.GetConfiguredSsidsAsync();
if (tobj_SSIDs != null && tobj_SSIDs.Contains(App.gvm_AppSettings.WifiSSID))
{
// We are already connected -- just return
lobj_WifiConfiguredEventArgs.ConnectionStatus = FlexConnectionStatus.eAlreadyConnected;
}
else
{
var tobj_WifiConfig = new NEHotspotConfiguration(App.gvm_AppSettings.WifiSSID, App.gvm_AppSettings.WifiPassword, false);
tobj_WifiManager.ApplyConfiguration(tobj_WifiConfig, async (error) =>
{
if (error != null)
{
lobj_WifiConfiguredEventArgs.ConnectionStatus = FlexConnectionStatus.eErrorEstablishingConnection;
lobj_WifiConfiguredEventArgs.ErrorMessage = error.ToString();
}
else
{
lobj_WifiConfiguredEventArgs.ConnectionStatus = FlexConnectionStatus.eConnectionEstablished;
}
});
}
}
catch(Exception ex)
{
lobj_WifiConfiguredEventArgs.ConnectionStatus = FlexConnectionStatus.eErrorEstablishingConnection;
lobj_WifiConfiguredEventArgs.ErrorMessage = ex.Message;
lobj_WifiConfiguredEventArgs.ErrorException = ex;
App.ProcessException(ex);
}
return lobj_WifiConfiguredEventArgs;
}
}
Someone asked for the socket code so here it is. To be clear, the socket code connects and communicates fine in iOS when the access point has an internet connection. It also works fine in all the android calls.
using FCISelfCheckIn;
using FCISelfCheckIn.Resources;
using FCISharedAll.FCICommObjects;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using static FCISharedAll.FCIEnums.FlexEnums;
namespace FCISelfCheckIn
{
// This template use base socket syntax to change Pattern. (like Send, Receive, and so on)
// Convert to Task-based Asynchronous Pattern. (TAP)
public static class AsynchronousClientSocket
{
private static bool ib_IsConnected = false;
private static Socket iobj_Client = null;
public static async Task<MasterDataObject> SendMessage(string ps_IPAddress, int pi_Port, ge_CommunicationType pe_CommicationType,
string JSONData)
{
MasterDataObject lobj_response = new MasterDataObject();
try
{
//We should already be connected by the time we get here so just continue
//However if we are not - try to connect again
if (!ib_IsConnected)
{
// Establish the remote endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse(ps_IPAddress);
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, pi_Port);
// Create a TCP/IP socket.
iobj_Client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
ib_IsConnected = await iobj_Client.ConnectAsync(remoteEndPoint).ConfigureAwait(false);
}
if (ib_IsConnected)
{
var bytesSent = await iobj_Client.SendAsync(JSONData).ConfigureAwait(false);
// Receive the response from the remote device.
var ls_MasterDataObject = await iobj_Client.ReceiveAsync(60).ConfigureAwait(false);
if (ls_MasterDataObject == null)
{
lobj_response = new MasterDataObject();
lobj_response.CommunicationType = ge_CommunicationType.e_Error;
}
else
{
//deserialize the master data object in order to return it to the client
lobj_response = App.gvm_CommunicationHelper.DeserializeMasterDataObject(ls_MasterDataObject);
iobj_Client.Shutdown(SocketShutdown.Both);
}
}
else
{
lobj_response.CommunicationType = ge_CommunicationType.e_Error;
lobj_response.JSONDataObject = JsonConvert.SerializeObject(AppResources.ServerConnectionError);
}
// Release the socket.
iobj_Client.Close();
}
catch (Exception ex)
{
App.ProcessException(ex);
}
return lobj_response;
}
private static Task<bool> ConnectAsync(this Socket client, IPEndPoint remoteEndPoint)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (remoteEndPoint == null) throw new ArgumentNullException(nameof(remoteEndPoint));
return Task.Run(() => Connect(client, remoteEndPoint));
}
private static bool Connect(this Socket client, EndPoint remoteEndPoint)
{
bool lb_ReturnValue = true;
try
{
if (client == null || remoteEndPoint == null)
{
lb_ReturnValue = false;
}
else
{
client.Connect(remoteEndPoint);
}
}
catch (System.Net.Sockets.SocketException Socketex)
{
lb_ReturnValue = false;
if (Socketex.ErrorCode != 10061 && Socketex.ErrorCode != 10065)
{
//Dont log if the host is not running.
App.ProcessException(Socketex);
}
}
catch (Exception ex)
{
App.ProcessException(ex);
lb_ReturnValue = false;
}
return lb_ReturnValue;
}
private static async Task<string> ReceiveAsync(this Socket client, int waitForFirstDelaySeconds = 10)
{
if (client == null) throw new ArgumentNullException(nameof(client));
Debug.WriteLine("Receive Message 1");
// Timeout for wait to receive and prepare data.
for (var i = 0; i < waitForFirstDelaySeconds; i++)
{
if (client.Available > 0)
break;
await Task.Delay(3000).ConfigureAwait(false);
}
// return null If data is not available.
if (client.Available < 1)
return null;
Debug.WriteLine("Receive Message 2");
// Size of receive buffer.
const int bufferSize = 1024;
var buffer = new byte[bufferSize];
// Get data
var response = new StringBuilder(bufferSize);
do
{
var size = Math.Min(bufferSize, client.Available);
await Task.Run(() => client.Receive(buffer)).ConfigureAwait(false);
var ts_CurrentSegment = Encoding.ASCII.GetString(buffer, 0, size);
if (ts_CurrentSegment.Length > 0)
{
response.Append(Encoding.ASCII.GetString(buffer, 0, size));
}
} while (!response.ToString().EndsWith(FCIEndOfFile));
// Return result.
return response.ToString().Replace(FCIEndOfFile, "");
}
private static async Task<int> SendAsync(this Socket client, string data)
{
var byteData = Encoding.ASCII.GetBytes(data);
return await SendAsync(client, byteData, 0, byteData.Length, 0).ConfigureAwait(false);
}
private static Task<int> SendAsync(this Socket client, byte[] buffer, int offset,
int size, SocketFlags socketFlags)
{
if (client == null) throw new ArgumentNullException(nameof(client));
return Task.Run(() => client.Send(buffer, offset, size, socketFlags));
}
public async static Task<bool> ForcePermissions(string ps_IPAddress, int pi_Port)
{
bool lb_ReturnValue = false;
try
{
IPAddress ipAddress = IPAddress.Parse(ps_IPAddress);
//This is only done to force the local network permissions access in iOS 14.
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, pi_Port);
// Create a TCP/IP socket.
iobj_Client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
ib_IsConnected = await iobj_Client.ConnectAsync(remoteEndPoint).ConfigureAwait(false);
if (ib_IsConnected)
{
Debug.WriteLine("GEORGE Permissions Connected");
//client.Shutdown(SocketShutdown.Both);
//client.Close();
lb_ReturnValue = true;
}
else
{
Debug.WriteLine("George Permissions not Connected");
}
}
catch (Exception ex)
{
//Just skip if there is an exception
App.ProcessException(ex);
}
return lb_ReturnValue;
}
}
}

How to timeout Firebase Task in Unity

This issue is driving me nuts :)
Assuming that I have a simple async Task:
async Task AddPoints()
{
await usersDbReference.Child(currentUser).Child("Score").SetValueAsync(newScore).ContinueWith(task =>
{
if(task.IsFaulted || task.IsCanceled)
{
Debug.Log("Couldn't complete task");
}
});
}
What is the simplest way to add the timeout, for example 10 seconds, after which I will show pop up to the user to check his/her internet connection?
Thank you in advance!
EDIT:
I tried below code but it makes the unity crash:
int timeout = 1000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
// task completed within timeout
} else {
// timeout logic
}
I'm using Unity (api compatibility level .Net Standard 2.0, I assume that crash is because of this?)
What I want to achieve:
In case the user doesn't have the internet connection I want to either timeout the task and cancel it or just cancel it after finding out there is no internet connection.
EDIT:
I modified the code. So I have a simple task with cancel token:
async Task CheckTask(CancellationToken csToken)
{
string firstChild = "user";
string secondChild = "testuser";
await FirebaseDatabase.DefaultInstance.RootReference.Child(firstChild).Child(secondChild).GetValueAsync().ContinueWith(task =>
{
if(task.IsFaulted || task.IsCanceled)
{
Debug.Log("Task was canceled");
}
});
}
Then I'm calling it from async void:
public async void FirebaseLogin()
{
bool taskDidntComplete = false;
Debug.Log("Started task");
CancellationTokenSource cs = new CancellationTokenSource();
try
{
var loginTask = CheckTask(cs.Token);
if(loginTask.IsCanceled)
{
Debug.Log("Canceled");
}
if (await Task.WhenAny(loginTask, Task.Delay(10000)) == loginTask)
{
taskDidntComplete = false;
}
else
{
taskDidntComplete = true;
Debug.Log(taskDidntComplete);
cs.Cancel();
throw new TimeoutException();
}
}
catch (Exception e)
{
Debug.Log(e);
}
finally
{
}
}
And while everything works fine and it shows the exception, it doesn't cancel the task. Would be very grateful if someone could tell me what I'm doing wrong.
EDIT2: Works perfect in Unity, doesnt work on Android... Anyone can help? I'm desperate now haha
public async void FirebaseLogin()
{
Debug.Log("Started task");
CancellationTokenSource cs = new CancellationTokenSource();
try
{
var loginTask = CheckTask(cs.Token);
if(loginTask.IsCanceled)
{
Debug.Log("Canceled");
netTestCheck.text = "Canceled";
}
if (await Task.WhenAny(loginTask, Task.Delay(10000)) == loginTask)
{
//netTestCheck.text = "Completed";
}
else
{
netTestCheck.text = "Failed";
cs.Cancel(false);
//throw new TimeoutException();
}
cs.Token.ThrowIfCancellationRequested();
}
catch (Exception e)
{
netTestCheck.text = "Failed2";
Debug.Log(e);
}
finally
{
}
It would help if you could share the exception or stack trace of the crash (integrating Crashlytics could help if you're already in the Firebase ecosystem).
Although I can't spy anything that looks particularly bad in your sample code, if the actual Task fails for whatever reason (say you turn on airplane mode to test, and a suitable exception is raised before your timeout) an exception will get raised there that you aren't handling.
I'd suggest putting a try/catch around your block like:
try {
int timeout = 1000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
// task completed within timeout
} else {
// timeout logic
}
} catch (Exception e) {
Debug.LogError($"{e} occurred!");
}
It's likely to be a DatabaseException, but I'd check first before you get more specific than Exception.
Let me know if that helps!
--Patrick
It unfortunately won't work on Android because app will keep on calling to Firebase. Fortunately found the way around :D

Sockets: .NET Core 2 server, HTML5 client cannot connect

I've run into a problem with socket server. Hope any of you might help me.
I have server built in .NET Core running on Debian which worked fine for clients made in .NET, but when I try to use HTML client it never gets past handshake.
Here's my example server:
class Program
{
public static TcpListener listener;
private static List<ClientPacket> clients;
private const int port = 4245;
private const int bufferSize = 1024;
static void Main(string[] args)
{
clients = new List<ClientPacket>();
listener = new TcpListener(IPAddress.Any, port);
listener.Start();
StartListening();
while (true)
{
}
}
private static void StartListening()
{
listener.BeginAcceptTcpClient(AcceptClient, listener);
}
private static void AcceptClient(IAsyncResult res)
{
TcpClient client = listener.EndAcceptTcpClient(res);
client.NoDelay = true;
ClientPacket packet = new ClientPacket(client);
clients.Add(packet);
Console.WriteLine("Client connected");
client.Client.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(ReceiveMessage), packet);
StartListening();
}
private static void ReceiveMessage(IAsyncResult res)
{
ClientPacket packet = (ClientPacket)res.AsyncState;
Socket s = packet.client.Client;
try
{
if (s.EndReceive(res) > 0)
{
s.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(ReceiveMessage), packet);
}
else
{
clients.Remove(packet);
s.Close();
packet = null;
}
}
catch (Exception e)
{
clients.Remove(packet);
s.Close();
packet = null;
}
}
It simply accepts clients, adds them to list and removes them after connection is lost. Problem is when I try it with this HTML5 client (copied from example tutorial):
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window)
{
var ws = new WebSocket("ws://serverIP:4245");
ws.onopen = function()
{
ws.send("Message to send");
alert("Message is sent...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
alert("Message is received...");
};
ws.onclose = function()
{
alert("Connection is closed...");
};
window.onbeforeunload = function(event) {
socket.close();
};
}
else
{
alert("WebSocket NOT supported by your Browser!");
}
}
</script>
</head>
<body>
<div id="sse">
Run WebSocket
</div>
</body>
</html>
Problem is, that with this I never see alert from 'onopen' function so it's not opened properly and readystatus is kept as 'connecting' instead of 'connected' all the time.
I've read a about response from server with some hash to acknowledge and finish handshake, but seen it in older examples of .NET and not with this TcpListener from Core 2... so I thought it's a part of BeginAcceptTcpClient function... and since it worked with .NET client I'm not really sure where is mistake.
Can anybody help me with this or hint how to implement handshake hash response, please?
Ok I found a problem. Client really did expected a hash in response to finish handshake... still don't undeastand why HTML did and .NET Client didn't want it.
I've created a new method for handshake to send required response:
private static void CompleteHandshake(IAsyncResult res)
{
ClientPacket packet = (ClientPacket)res.AsyncState;
Socket s = packet.client.Client;
try
{
if (s.EndReceive(res) > 0)
{
var data = ByteArray.ReadString(packet.buffer);
if (new Regex("^GET").IsMatch(data))
{
Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
+ "Connection: Upgrade" + Environment.NewLine
+ "Upgrade: websocket" + Environment.NewLine
+ "Sec-WebSocket-Accept: "
+ Convert.ToBase64String(
SHA1.Create().ComputeHash(
Encoding.UTF8.GetBytes(
new Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
)
)
) + Environment.NewLine
+ Environment.NewLine);
Console.WriteLine("Packet incoming");
s.Send(response, 0, response.Length, SocketFlags.None);
}
s.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(ReceiveMessage), packet);
}
else
{
clients.Remove(packet);
s.Close();
packet = null;
}
}
catch (Exception e)
{
clients.Remove(packet);
s.Close();
packet = null;
}
}
Then the only change in old code is in listener method AcceptClient where simple change method parameter of BeginReceive to redirect onto CompleteHandshake.
private static void AcceptClient(IAsyncResult res)
{
TcpClient client = listener.EndAcceptTcpClient(res);
client.NoDelay = true;
ClientPacket packet = new ClientPacket(client);
clients.Add(packet);
client.Client.BeginReceive(packet.buffer, 0, bufferSize, 0, new AsyncCallback(CompleteHandshake), packet);
StartListening();
}
That new method CompleteHandshake after sending hash response will redirect back to the old ReceiveMessage method where you can handle message however you need.

C# detect TCP client disconnection

I am working on TCP multithread server with C# window application form, and I am trying to detect if the machine of client is shutdown and disconnects from the server. I have read some posts and have some ideas:
How to determine if the tcp is connected or not?
Instantly detect client disconnection from server socket
But I'm not sure where to call the function IsConnected
My code is like the following:
public BindingList<Tablet> tabletList = new BindingList<Tablet>();
private Socket socket_Server = null;
private Thread myThread = null;
private Socket socket_Connect = null;
private Dictionary<string, Socket> dic = new Dictionary<string, Socket> { };
private string RemoteEndPoint;
socket_Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ServerIP = IPAddress.Parse("192.168.2.146");
IPEndPoint point = new IPEndPoint(ServerIP, portNum);
socket_Server.Bind(point);
socket_Server.Listen(50);
myThread = new Thread(Listen_Disp);
myThread.IsBackground = true;
myThread.Start();
Console.WriteLine("Server start");
private void Listen_Disp()
{
try
{
while (true)
{
//This is not working
for (int i = 0; i < tabletList.Count; i++)
{
if (!SocketConnected(dic[tabletList[i].ip]))
{
Console.WriteLine(RemoteEndPoint + "disconnected");
}
}
try
{
socket_Connect = socket_Server.Accept();
RemoteEndPoint = socket_Connect.RemoteEndPoint.ToString();
Console.WriteLine(RemoteEndPoint + " is connected");
dic.Add(RemoteEndPoint, socket_Connect);
Tablet newTablet = new Tablet();
newTablet.ip = RemoteEndPoint;
newTablet.status = "Online";
tabletList.Add(newTablet);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Console.WriteLine("end of while");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
static class SocketExtensions
{
public static bool IsConnected(this Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
}
Thanks for help.
There's a lot of misinformation on that subject, and some of it is present in the questions you linked. The only reliable way to detect a TCP disconnection is to try to write to the connection. A read timeout can also indicate a dropped connection, but it may mean a lot of other things too, such as a stuck server. An EOS condition when reading indicates a graceful disconnect. The IsConnected() method and friends only give you a history of what you have done to this socket: they don't give you the current state of the connection. They can't, because, absent a pending write request, there is no state to
know. TCP doesn't maintain anything akin to a dial tone.

Resources