I have written a class that is essentially a heartbeat, the client sends a message to the server every x number of seconds.
Shamelessly stolen Send code
private void SendUdpPacket() {
byte[] data = new byte[1024];
Socket udpClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
data = Encoding.ASCII.GetBytes("lubdub");
udpClientSocket.SendTo(data, 0, data.Length, SocketFlags.None, ipep);
}
Shamelessly stolen Receive code
void ReceiveData(IAsyncResult iar) {
byte[] buffer = new byte[1024];
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceiveFrom(iar, ref tempRemoteEP);
string stringData = Encoding.ASCII.GetString(buffer, 0, recv);
Console.WriteLine(stringData);
lastUpdate = DateTime.Now.ToUniversalTime();
if (!this.IsDisposed) {
udpServerSocket.BeginReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref ep, new AsyncCallback(ReceiveData), udpServerSocket);
}
This is then monitored by an internal timer
private void clTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
try {
SendUdpPacket();
connected = true;
} catch {
connected = false;
}
}
private void srTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
// Calculate the Timespan since the Last Update from the Client.
timeSinceLastHeartbeat = DateTime.Now.ToUniversalTime() - lastUpdate;
if (timeSinceLastHeartbeat > TimeSpan.FromMilliseconds(Timer.Interval))
connected = false;
else
connected = true;
}
if the message is successful then the socket is connected, this is shown via a public boolean value connected
So in my application I would then have a timer running the following:
private void ServerCheck() {
if (heartin.connected) {
GKstat = true;
GKStatus.Text = "GateKeeper Status: Connected";
} else {
GKstat = false;
GKStatus.Text = "GateKeeper Status: Disconnected";
}
}
However this is not ideal, as it requires timer on the client or server to constantly check if the Heart
is connected.
I was wondering if it would be beneficial to convert this to a set of events,
say OnConnectionLost
and OnConnected
I've been looking around and reading various pages, they've only confused me further.
This is what I have so far
public delegate void OnConnectionLost(Heart sender, EventArgs e);
public delegate void OnConnected(object sender, EventArgs e);
public event OnConnectionLost ConnectionLost;
My question is, would this be beneficial, and if so, how would I create the event in such a way that it would only fire when connection state changes?
This is one of the scenarios where booleans are evil: I strongly recommend you make an enum
such as:
public enum ConnectionState
{
Disconnected = 0,
Disconnecting = 1,
Connecting = 2,
Connected = 3,
// etc.
}
You can then use this for a property such as ConnectionState
. In addition, it's common practice to use the standard EventHandler<T>
delegate instead of your own custom delegate types. For example:
public sealed class ConnectionStateEventArgs : EventArgs
{
public ConnectionState ConnectionState { get; private set; }
public ConnectionStateEventArgs(ConnectionState connectionState)
{
ConnectionState = connectionState;
}
}
public event EventHandler<ConnectionStateEventArgs> ConnectionStateChanged;
This will allow you to expand your connection states beyond the simple "on-off" that you have right now. The ConnectionState
property coupled with the ConnectionStateChanged
event is a common practice that I've noticed across various APIs.
To have it only fire when the connection state really changes, simply add a body to your ConnectionState
property:
private ConnectionState _connectionState;
public ConnectionState ConnectionState
{
get { return _connectionState; }
set
{
if (value != _connectionState)
{
_connectionState = value;
var tmp = ConnectionStateChanged;
if (tmp != null)
tmp (this, new ConnectionStateEventArgs(value));
}
}
}
All you then need do is assign a different value to the property and the event will fire.