âAlways stay connectedâ mechanism for socket connection
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I'm calling Connect()
for the first time I connect, I am then checking if the connection is still connected every 10 seconds if it is not connected it attempts to re-connect.
public class ClientHandler : ISocketHandler, IDisposable
private readonly Socket _socket;
private readonly byte _buffer;
private ISession _session;
private bool _hasConnected;
public ClientHandler()
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_buffer = new byte[8192];
var timer = new Timer
Interval = 30000
;
timer.Elapsed += ElapsedTimer;
timer.Enabled = true;
private void ElapsedTimer(object sender, ElapsedEventArgs e)
if (!CoreUtilities.IsConnected(_socket))
Connect();
public void Connect()
var host = _session.ConfigHandler["server.host"];
var port = short.Parse(_session.ConfigHandler["server.port"]);
try
_socket.Connect(new IPEndPoint(IPAddress.Parse(host), port));
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnIncomingData, _socket);
CoreUtilities.LogToConsole("Successfully established a connection to the server.");
catch (SocketException)
CoreUtilities.LogToConsole("Failed to establish a connection with the server.");
finally
if (_socket.Connected && CoreUtilities.IsConnected(_socket))
Send(new SocketPasswordComposer(_session.ConfigHandler["server.password"]));
Here is the method I use to determine if the socket is fully connected to the server.
public static bool IsConnected(Socket socket)
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
I feel that what I have coded above could be improved a lot.
c# .net error-handling socket
add a comment |Â
up vote
3
down vote
favorite
I'm calling Connect()
for the first time I connect, I am then checking if the connection is still connected every 10 seconds if it is not connected it attempts to re-connect.
public class ClientHandler : ISocketHandler, IDisposable
private readonly Socket _socket;
private readonly byte _buffer;
private ISession _session;
private bool _hasConnected;
public ClientHandler()
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_buffer = new byte[8192];
var timer = new Timer
Interval = 30000
;
timer.Elapsed += ElapsedTimer;
timer.Enabled = true;
private void ElapsedTimer(object sender, ElapsedEventArgs e)
if (!CoreUtilities.IsConnected(_socket))
Connect();
public void Connect()
var host = _session.ConfigHandler["server.host"];
var port = short.Parse(_session.ConfigHandler["server.port"]);
try
_socket.Connect(new IPEndPoint(IPAddress.Parse(host), port));
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnIncomingData, _socket);
CoreUtilities.LogToConsole("Successfully established a connection to the server.");
catch (SocketException)
CoreUtilities.LogToConsole("Failed to establish a connection with the server.");
finally
if (_socket.Connected && CoreUtilities.IsConnected(_socket))
Send(new SocketPasswordComposer(_session.ConfigHandler["server.password"]));
Here is the method I use to determine if the socket is fully connected to the server.
public static bool IsConnected(Socket socket)
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
I feel that what I have coded above could be improved a lot.
c# .net error-handling socket
2
What actually makes you feeling wrong about what you're doing there?
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 17 at 1:01
Not wrong, just not very practical. It feels like I'm doing a lot of work to delegate a small job which can be done much easier, although I can't see a better way as of now.
â user692959239
Apr 17 at 1:07
2
Please post all code of this class.
â Heslacher
Apr 17 at 4:20
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I'm calling Connect()
for the first time I connect, I am then checking if the connection is still connected every 10 seconds if it is not connected it attempts to re-connect.
public class ClientHandler : ISocketHandler, IDisposable
private readonly Socket _socket;
private readonly byte _buffer;
private ISession _session;
private bool _hasConnected;
public ClientHandler()
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_buffer = new byte[8192];
var timer = new Timer
Interval = 30000
;
timer.Elapsed += ElapsedTimer;
timer.Enabled = true;
private void ElapsedTimer(object sender, ElapsedEventArgs e)
if (!CoreUtilities.IsConnected(_socket))
Connect();
public void Connect()
var host = _session.ConfigHandler["server.host"];
var port = short.Parse(_session.ConfigHandler["server.port"]);
try
_socket.Connect(new IPEndPoint(IPAddress.Parse(host), port));
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnIncomingData, _socket);
CoreUtilities.LogToConsole("Successfully established a connection to the server.");
catch (SocketException)
CoreUtilities.LogToConsole("Failed to establish a connection with the server.");
finally
if (_socket.Connected && CoreUtilities.IsConnected(_socket))
Send(new SocketPasswordComposer(_session.ConfigHandler["server.password"]));
Here is the method I use to determine if the socket is fully connected to the server.
public static bool IsConnected(Socket socket)
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
I feel that what I have coded above could be improved a lot.
c# .net error-handling socket
I'm calling Connect()
for the first time I connect, I am then checking if the connection is still connected every 10 seconds if it is not connected it attempts to re-connect.
public class ClientHandler : ISocketHandler, IDisposable
private readonly Socket _socket;
private readonly byte _buffer;
private ISession _session;
private bool _hasConnected;
public ClientHandler()
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_buffer = new byte[8192];
var timer = new Timer
Interval = 30000
;
timer.Elapsed += ElapsedTimer;
timer.Enabled = true;
private void ElapsedTimer(object sender, ElapsedEventArgs e)
if (!CoreUtilities.IsConnected(_socket))
Connect();
public void Connect()
var host = _session.ConfigHandler["server.host"];
var port = short.Parse(_session.ConfigHandler["server.port"]);
try
_socket.Connect(new IPEndPoint(IPAddress.Parse(host), port));
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnIncomingData, _socket);
CoreUtilities.LogToConsole("Successfully established a connection to the server.");
catch (SocketException)
CoreUtilities.LogToConsole("Failed to establish a connection with the server.");
finally
if (_socket.Connected && CoreUtilities.IsConnected(_socket))
Send(new SocketPasswordComposer(_session.ConfigHandler["server.password"]));
Here is the method I use to determine if the socket is fully connected to the server.
public static bool IsConnected(Socket socket)
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
I feel that what I have coded above could be improved a lot.
c# .net error-handling socket
edited Apr 17 at 4:04
200_success
123k14142399
123k14142399
asked Apr 17 at 0:59
user692959239
191
191
2
What actually makes you feeling wrong about what you're doing there?
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 17 at 1:01
Not wrong, just not very practical. It feels like I'm doing a lot of work to delegate a small job which can be done much easier, although I can't see a better way as of now.
â user692959239
Apr 17 at 1:07
2
Please post all code of this class.
â Heslacher
Apr 17 at 4:20
add a comment |Â
2
What actually makes you feeling wrong about what you're doing there?
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 17 at 1:01
Not wrong, just not very practical. It feels like I'm doing a lot of work to delegate a small job which can be done much easier, although I can't see a better way as of now.
â user692959239
Apr 17 at 1:07
2
Please post all code of this class.
â Heslacher
Apr 17 at 4:20
2
2
What actually makes you feeling wrong about what you're doing there?
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 17 at 1:01
What actually makes you feeling wrong about what you're doing there?
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 17 at 1:01
Not wrong, just not very practical. It feels like I'm doing a lot of work to delegate a small job which can be done much easier, although I can't see a better way as of now.
â user692959239
Apr 17 at 1:07
Not wrong, just not very practical. It feels like I'm doing a lot of work to delegate a small job which can be done much easier, although I can't see a better way as of now.
â user692959239
Apr 17 at 1:07
2
2
Please post all code of this class.
â Heslacher
Apr 17 at 4:20
Please post all code of this class.
â Heslacher
Apr 17 at 4:20
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
4
down vote
I see there is problem in the usage to Timer. Consider the case if the server takes more time (> 5000) to connect, than the timer interval specified (3000) specified. Then the timer elapsed event will fire again though the first elapsed event is not yet finished. In order to avoid this stop the timer in the begin of Connect() and start the timer in end of Connect().
add a comment |Â
up vote
0
down vote
I would like to share a sample solution based on following aspects
- Client is only responsible for Sending, Receiving, Connecting and disconnecting from Server.
- Wrapper class is responsible for state management of Client, like initialization, dispose, re-connection, processing the received data, forwarding data to client, decision based on the connection state of Client with server
In this way you could able to reuse the Client and add have different wrapper classes based on the functionality like (Active-Active client, Active - Passive client, Broad cast clients)...
I would like to share the abstract code (doesn't have any DI or pattern implementation), you can modify according to your requirement.
public enum LinkStatus
Connected,
Disconnected
MessageEventArgs Event args raised by client, during the sending and reception of message to server, which includes the data and status.
public class MessageEventArgs : EventArgs
public byte Message get; private set;
public bool Result get; private set;
public int Index get; private set;
public MessageEventArgs(int pIndex, byte pData, bool pResult)
Message = pData;
Result = pResult;
Index = pIndex;
ServerEventArgs Event args class holding server details
public class ServerEventArgs : EventArgs
public IPAddress IP get; private set;
public int Port get; private set;
public int Index get; private set;
public ServerEventArgs(int pIndex, IPEndPoint pServerEndPoint)
this.IP = pServerEndPoint.Address;
this.Port = pServerEndPoint.Port;
this.Index = pIndex;
MyTcpClient class is shown below, which will do following tasks
a. Expose methods to start and stop communication with server
b. Expose Connection Link status
c. Raise events like MessageSentSuccessfully, MessageSendingFailed, Disconnected, ConnectingSucceeded, MessageReceived.
public class MyTcpClient
private int mIndex;
private LinkStatus mConnectionStatus = LinkStatus.Disconnected;
private Socket mClientSocket = null;
private NetworkStream mNetworkStream = null;
private BackgroundWorker mBwReceiver;
private IPEndPoint mServerEP = null;
private IPEndPoint mClientEP = null;
private Semaphore mSendSemaphore;
private int mConnectionSleepTime = 5000;
public MyTcpClient(int pIndex, string pServerAddress, int pPortNumber)
this.mIndex = pIndex;
this.mSendSemaphore = new Semaphore(1, 1);
IPAddress address = IPAddress.Parse(pServerAddress);
IPEndPoint endPoint = new IPEndPoint(address, pPortNumber);
this.mServerEP = endPoint;
this.mClientEP = new IPEndPoint(IPAddress.Any, 0);
this.mSendSemaphore = new Semaphore(1, 1);
public event EventHandler<MessageEventArgs> MessageReceived;
public event EventHandler<MessageEventArgs> MessageSent;
public event EventHandler<MessageEventArgs> MessageSendingFailed;
public event EventHandler<ServerEventArgs> Disconnected;
public event EventHandler<ServerEventArgs> ConnectingSucceeded;
public LinkStatus ConnectionStatus
get
if (this.mConnectionStatus == LinkStatus.Connected)
bool result = false;
try
if (this.mClientSocket != null)
result = !(this.mClientSocket.Poll(1, SelectMode.SelectRead) && this.mClientSocket.Available == 0);
catch
if (result)
this.mConnectionStatus = LinkStatus.Connected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
return this.mConnectionStatus;
public void ConnectToServer(int pSleepingInterval)
this.mConnectionSleepTime = pSleepingInterval;
BackgroundWorker bwConnector = new BackgroundWorker();
bwConnector.DoWork += new DoWorkEventHandler(this.BwConnector_DoWork);
bwConnector.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwConnector_RunWorkerCompleted);
bwConnector.RunWorkerAsync();
public void SendCommand(byte pMessage)
if (this.ConnectionStatus == LinkStatus.Connected)
BackgroundWorker bwSendWorker = new BackgroundWorker();
bwSendWorker.DoWork += new DoWorkEventHandler(this.BwSendWorker_DoWork);
bwSendWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwSendWorker_RunWorkerCompleted);
bwSendWorker.WorkerSupportsCancellation = true;
bwSendWorker.RunWorkerAsync(pMessage);
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, pMessage, false));
public void DisconnectFromServer(bool pCanRaise)
try
if (this.ConnectionStatus == LinkStatus.Connected)
try
this.mBwReceiver.CancelAsync();
this.mBwReceiver.Dispose();
catch
try
this.mClientSocket.Shutdown(SocketShutdown.Both);
this.mClientSocket.Close();
catch
finally
this.mClientSocket = null;
this.SocketDisconnected(pCanRaise);
protected virtual void OnMessageReceived(MessageEventArgs e)
if (this.MessageReceived != null)
this.MessageReceived(this, e);
protected virtual void OnMessageSent(MessageEventArgs e)
if (this.MessageSent != null)
this.MessageSent(this, e);
protected virtual void OnMessageSendingFailed(MessageEventArgs e)
if (this.MessageSendingFailed != null)
this.MessageSendingFailed(this, e);
protected virtual void OnServerDisconnected(ServerEventArgs e)
this.DisconnectFromServer(true);
protected virtual void OnConnectionSucceeded()
this.mConnectionStatus = LinkStatus.Connected;
if (this.ConnectingSucceeded != null)
this.ConnectingSucceeded(this, new ServerEventArgs(this.mIndex, this.mServerEP));
protected virtual void OnConnectingFailed()
this.DisconnectFromServer(true);
private void BwConnector_DoWork(object sender, DoWorkEventArgs e)
bool result = false;
try
Thread.Sleep(this.mConnectionSleepTime);
this.mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.mClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.mClientSocket.Bind(this.mClientEP);
// thread gets block until it gets response for server
this.mClientSocket.Connect(this.mServerEP);
result = true;
//// catch generic exception
catch
result = false;
e.Result = result;
private void BwConnector_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
//// raise connection fail event if client not connected to server
if (!(bool)e.Result)
this.OnConnectingFailed();
else
this.mNetworkStream = new NetworkStream(this.mClientSocket);
this.mBwReceiver = new BackgroundWorker();
this.mBwReceiver.WorkerSupportsCancellation = true;
this.mBwReceiver.DoWork += new DoWorkEventHandler(this.BwReceiver_DoWork);
this.mBwReceiver.RunWorkerAsync();
this.OnConnectionSucceeded();
((BackgroundWorker)sender).Dispose();
// catch generic exception if any thing happens, this is for safe
catch
private void BwReceiver_DoWork(object sender, DoWorkEventArgs e)
while (this.ConnectionStatus == LinkStatus.Connected && (this.mNetworkStream != null))
try
if (this.mNetworkStream.CanRead)
byte data = new byte[1024];
int noOfBytesRead = 0;
noOfBytesRead = this.mNetworkStream.Read(data, 0, data.Length);
if (noOfBytesRead > 0)
byte receivedData = new byte[noOfBytesRead];
Array.Copy(data, receivedData, receivedData.Length);
MessageEventArgs mArgs = new MessageEventArgs(this.mIndex, receivedData, true);
this.OnMessageReceived(mArgs);
else
catch
break;
this.OnServerDisconnected(new ServerEventArgs(this.mIndex, this.mServerEP));
private void BwSendWorker_DoWork(object sender, DoWorkEventArgs e)
byte sendData = (byte)e.Argument;
MessageEventArgs args = null;
//// check for connectivity
if (this.ConnectionStatus == LinkStatus.Connected && sendData.Length > 0)
try
this.mSendSemaphore.WaitOne();
this.mNetworkStream.Write(sendData, 0, sendData.Length);
this.mNetworkStream.Flush();
this.mSendSemaphore.Release();
args = new MessageEventArgs(this.mIndex, sendData, true);
e.Result = args;
//// catch generic exception, for safe
catch
args = new MessageEventArgs(this.mIndex, sendData, false);
this.mSendSemaphore.Release();
e.Result = args;
else
args = new MessageEventArgs(this.mIndex, sendData, false);
e.Result = args;
private void BwSendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
MessageEventArgs args = e.Result as MessageEventArgs;
if (args != null)
// raised when message is sent to server successfully
if ((!e.Cancelled && e.Error == null) && (bool)args.Result)
this.OnMessageSent(new MessageEventArgs(this.mIndex, args.Message, args.Result));
// raised when message sending is failed to server
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, args.Message, args.Result));
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, null, false));
((BackgroundWorker)sender).Dispose();
catch
public void SocketDisconnected(bool pCanRaise)
this.mConnectionStatus = LinkStatus.Disconnected;
if (this.Disconnected != null && pCanRaise)
this.Disconnected(this, new ServerEventArgs(this.mIndex, this.mServerEP));
MyTCPWrapper class is show below, which will do the following
a. Controls the life cycle of MyTCPClients, based on the connection status and message reception status.
b. Add multiple clients, to provide redundencies like (Active - Active, Active - Passive)...
public class MyTcpWrapper
private MyTcpClient mTcpClinet = null;
private bool mTransportConnectionStatus = false;
private int mReconnect = 10;
public int Reconnect
get
return this.mReconnect;
set
this.mReconnect = value;
public bool TransportConnectionStatus
get
bool result = false;
if(this.mTcpClinet != null)
if(this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
result = true;
return result;
public void InitializeTransport()
if (this.DeInitializeTransport())
this.mTcpClinet = new MyTcpClient(1, "serverAddress", 9000);
this.mTcpClinet.ConnectingSucceeded += new EventHandler<ServerEventArgs>(Transport_ConnectingSucceeded);
this.mTcpClinet.Disconnected += new EventHandler<ServerEventArgs>(Transport_Disconnected);
this.mTcpClinet.MessageReceived += new EventHandler<MessageEventArgs>(Transport_MessageReceived);
this.mTcpClinet.ConnectToServer(this.Reconnect);
public bool DeInitializeTransport()
bool result = true;
this.mReconnect = 0;
try
if (this.mTcpClinet != null)
this.mTcpClinet.MessageReceived -= this.Transport_MessageReceived;
this.mTcpClinet.Disconnected -= this.Transport_Disconnected;
this.mTcpClinet.ConnectingSucceeded -= this.Transport_ConnectingSucceeded;
this.mTcpClinet.DisconnectFromServer(false);
catch
finally
this.mTcpClinet = null;
return result;
public void SendData(byte pData)
if (this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
this.mTcpClinet.SendCommand(pData);
else
// take actions accordingly.
private void Transport_MessageReceived(object sender, MessageEventArgs e)
private void Transport_Disconnected(object sender, ServerEventArgs e)
this.mTcpClinet.ConnectToServer(this.mReconnect);
private void Transport_ConnectingSucceeded(object sender, ServerEventArgs e)
private void OnReceiveMessage(byte pData)
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
I see there is problem in the usage to Timer. Consider the case if the server takes more time (> 5000) to connect, than the timer interval specified (3000) specified. Then the timer elapsed event will fire again though the first elapsed event is not yet finished. In order to avoid this stop the timer in the begin of Connect() and start the timer in end of Connect().
add a comment |Â
up vote
4
down vote
I see there is problem in the usage to Timer. Consider the case if the server takes more time (> 5000) to connect, than the timer interval specified (3000) specified. Then the timer elapsed event will fire again though the first elapsed event is not yet finished. In order to avoid this stop the timer in the begin of Connect() and start the timer in end of Connect().
add a comment |Â
up vote
4
down vote
up vote
4
down vote
I see there is problem in the usage to Timer. Consider the case if the server takes more time (> 5000) to connect, than the timer interval specified (3000) specified. Then the timer elapsed event will fire again though the first elapsed event is not yet finished. In order to avoid this stop the timer in the begin of Connect() and start the timer in end of Connect().
I see there is problem in the usage to Timer. Consider the case if the server takes more time (> 5000) to connect, than the timer interval specified (3000) specified. Then the timer elapsed event will fire again though the first elapsed event is not yet finished. In order to avoid this stop the timer in the begin of Connect() and start the timer in end of Connect().
answered Apr 17 at 6:08
vishnu vardhan
1874
1874
add a comment |Â
add a comment |Â
up vote
0
down vote
I would like to share a sample solution based on following aspects
- Client is only responsible for Sending, Receiving, Connecting and disconnecting from Server.
- Wrapper class is responsible for state management of Client, like initialization, dispose, re-connection, processing the received data, forwarding data to client, decision based on the connection state of Client with server
In this way you could able to reuse the Client and add have different wrapper classes based on the functionality like (Active-Active client, Active - Passive client, Broad cast clients)...
I would like to share the abstract code (doesn't have any DI or pattern implementation), you can modify according to your requirement.
public enum LinkStatus
Connected,
Disconnected
MessageEventArgs Event args raised by client, during the sending and reception of message to server, which includes the data and status.
public class MessageEventArgs : EventArgs
public byte Message get; private set;
public bool Result get; private set;
public int Index get; private set;
public MessageEventArgs(int pIndex, byte pData, bool pResult)
Message = pData;
Result = pResult;
Index = pIndex;
ServerEventArgs Event args class holding server details
public class ServerEventArgs : EventArgs
public IPAddress IP get; private set;
public int Port get; private set;
public int Index get; private set;
public ServerEventArgs(int pIndex, IPEndPoint pServerEndPoint)
this.IP = pServerEndPoint.Address;
this.Port = pServerEndPoint.Port;
this.Index = pIndex;
MyTcpClient class is shown below, which will do following tasks
a. Expose methods to start and stop communication with server
b. Expose Connection Link status
c. Raise events like MessageSentSuccessfully, MessageSendingFailed, Disconnected, ConnectingSucceeded, MessageReceived.
public class MyTcpClient
private int mIndex;
private LinkStatus mConnectionStatus = LinkStatus.Disconnected;
private Socket mClientSocket = null;
private NetworkStream mNetworkStream = null;
private BackgroundWorker mBwReceiver;
private IPEndPoint mServerEP = null;
private IPEndPoint mClientEP = null;
private Semaphore mSendSemaphore;
private int mConnectionSleepTime = 5000;
public MyTcpClient(int pIndex, string pServerAddress, int pPortNumber)
this.mIndex = pIndex;
this.mSendSemaphore = new Semaphore(1, 1);
IPAddress address = IPAddress.Parse(pServerAddress);
IPEndPoint endPoint = new IPEndPoint(address, pPortNumber);
this.mServerEP = endPoint;
this.mClientEP = new IPEndPoint(IPAddress.Any, 0);
this.mSendSemaphore = new Semaphore(1, 1);
public event EventHandler<MessageEventArgs> MessageReceived;
public event EventHandler<MessageEventArgs> MessageSent;
public event EventHandler<MessageEventArgs> MessageSendingFailed;
public event EventHandler<ServerEventArgs> Disconnected;
public event EventHandler<ServerEventArgs> ConnectingSucceeded;
public LinkStatus ConnectionStatus
get
if (this.mConnectionStatus == LinkStatus.Connected)
bool result = false;
try
if (this.mClientSocket != null)
result = !(this.mClientSocket.Poll(1, SelectMode.SelectRead) && this.mClientSocket.Available == 0);
catch
if (result)
this.mConnectionStatus = LinkStatus.Connected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
return this.mConnectionStatus;
public void ConnectToServer(int pSleepingInterval)
this.mConnectionSleepTime = pSleepingInterval;
BackgroundWorker bwConnector = new BackgroundWorker();
bwConnector.DoWork += new DoWorkEventHandler(this.BwConnector_DoWork);
bwConnector.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwConnector_RunWorkerCompleted);
bwConnector.RunWorkerAsync();
public void SendCommand(byte pMessage)
if (this.ConnectionStatus == LinkStatus.Connected)
BackgroundWorker bwSendWorker = new BackgroundWorker();
bwSendWorker.DoWork += new DoWorkEventHandler(this.BwSendWorker_DoWork);
bwSendWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwSendWorker_RunWorkerCompleted);
bwSendWorker.WorkerSupportsCancellation = true;
bwSendWorker.RunWorkerAsync(pMessage);
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, pMessage, false));
public void DisconnectFromServer(bool pCanRaise)
try
if (this.ConnectionStatus == LinkStatus.Connected)
try
this.mBwReceiver.CancelAsync();
this.mBwReceiver.Dispose();
catch
try
this.mClientSocket.Shutdown(SocketShutdown.Both);
this.mClientSocket.Close();
catch
finally
this.mClientSocket = null;
this.SocketDisconnected(pCanRaise);
protected virtual void OnMessageReceived(MessageEventArgs e)
if (this.MessageReceived != null)
this.MessageReceived(this, e);
protected virtual void OnMessageSent(MessageEventArgs e)
if (this.MessageSent != null)
this.MessageSent(this, e);
protected virtual void OnMessageSendingFailed(MessageEventArgs e)
if (this.MessageSendingFailed != null)
this.MessageSendingFailed(this, e);
protected virtual void OnServerDisconnected(ServerEventArgs e)
this.DisconnectFromServer(true);
protected virtual void OnConnectionSucceeded()
this.mConnectionStatus = LinkStatus.Connected;
if (this.ConnectingSucceeded != null)
this.ConnectingSucceeded(this, new ServerEventArgs(this.mIndex, this.mServerEP));
protected virtual void OnConnectingFailed()
this.DisconnectFromServer(true);
private void BwConnector_DoWork(object sender, DoWorkEventArgs e)
bool result = false;
try
Thread.Sleep(this.mConnectionSleepTime);
this.mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.mClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.mClientSocket.Bind(this.mClientEP);
// thread gets block until it gets response for server
this.mClientSocket.Connect(this.mServerEP);
result = true;
//// catch generic exception
catch
result = false;
e.Result = result;
private void BwConnector_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
//// raise connection fail event if client not connected to server
if (!(bool)e.Result)
this.OnConnectingFailed();
else
this.mNetworkStream = new NetworkStream(this.mClientSocket);
this.mBwReceiver = new BackgroundWorker();
this.mBwReceiver.WorkerSupportsCancellation = true;
this.mBwReceiver.DoWork += new DoWorkEventHandler(this.BwReceiver_DoWork);
this.mBwReceiver.RunWorkerAsync();
this.OnConnectionSucceeded();
((BackgroundWorker)sender).Dispose();
// catch generic exception if any thing happens, this is for safe
catch
private void BwReceiver_DoWork(object sender, DoWorkEventArgs e)
while (this.ConnectionStatus == LinkStatus.Connected && (this.mNetworkStream != null))
try
if (this.mNetworkStream.CanRead)
byte data = new byte[1024];
int noOfBytesRead = 0;
noOfBytesRead = this.mNetworkStream.Read(data, 0, data.Length);
if (noOfBytesRead > 0)
byte receivedData = new byte[noOfBytesRead];
Array.Copy(data, receivedData, receivedData.Length);
MessageEventArgs mArgs = new MessageEventArgs(this.mIndex, receivedData, true);
this.OnMessageReceived(mArgs);
else
catch
break;
this.OnServerDisconnected(new ServerEventArgs(this.mIndex, this.mServerEP));
private void BwSendWorker_DoWork(object sender, DoWorkEventArgs e)
byte sendData = (byte)e.Argument;
MessageEventArgs args = null;
//// check for connectivity
if (this.ConnectionStatus == LinkStatus.Connected && sendData.Length > 0)
try
this.mSendSemaphore.WaitOne();
this.mNetworkStream.Write(sendData, 0, sendData.Length);
this.mNetworkStream.Flush();
this.mSendSemaphore.Release();
args = new MessageEventArgs(this.mIndex, sendData, true);
e.Result = args;
//// catch generic exception, for safe
catch
args = new MessageEventArgs(this.mIndex, sendData, false);
this.mSendSemaphore.Release();
e.Result = args;
else
args = new MessageEventArgs(this.mIndex, sendData, false);
e.Result = args;
private void BwSendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
MessageEventArgs args = e.Result as MessageEventArgs;
if (args != null)
// raised when message is sent to server successfully
if ((!e.Cancelled && e.Error == null) && (bool)args.Result)
this.OnMessageSent(new MessageEventArgs(this.mIndex, args.Message, args.Result));
// raised when message sending is failed to server
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, args.Message, args.Result));
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, null, false));
((BackgroundWorker)sender).Dispose();
catch
public void SocketDisconnected(bool pCanRaise)
this.mConnectionStatus = LinkStatus.Disconnected;
if (this.Disconnected != null && pCanRaise)
this.Disconnected(this, new ServerEventArgs(this.mIndex, this.mServerEP));
MyTCPWrapper class is show below, which will do the following
a. Controls the life cycle of MyTCPClients, based on the connection status and message reception status.
b. Add multiple clients, to provide redundencies like (Active - Active, Active - Passive)...
public class MyTcpWrapper
private MyTcpClient mTcpClinet = null;
private bool mTransportConnectionStatus = false;
private int mReconnect = 10;
public int Reconnect
get
return this.mReconnect;
set
this.mReconnect = value;
public bool TransportConnectionStatus
get
bool result = false;
if(this.mTcpClinet != null)
if(this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
result = true;
return result;
public void InitializeTransport()
if (this.DeInitializeTransport())
this.mTcpClinet = new MyTcpClient(1, "serverAddress", 9000);
this.mTcpClinet.ConnectingSucceeded += new EventHandler<ServerEventArgs>(Transport_ConnectingSucceeded);
this.mTcpClinet.Disconnected += new EventHandler<ServerEventArgs>(Transport_Disconnected);
this.mTcpClinet.MessageReceived += new EventHandler<MessageEventArgs>(Transport_MessageReceived);
this.mTcpClinet.ConnectToServer(this.Reconnect);
public bool DeInitializeTransport()
bool result = true;
this.mReconnect = 0;
try
if (this.mTcpClinet != null)
this.mTcpClinet.MessageReceived -= this.Transport_MessageReceived;
this.mTcpClinet.Disconnected -= this.Transport_Disconnected;
this.mTcpClinet.ConnectingSucceeded -= this.Transport_ConnectingSucceeded;
this.mTcpClinet.DisconnectFromServer(false);
catch
finally
this.mTcpClinet = null;
return result;
public void SendData(byte pData)
if (this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
this.mTcpClinet.SendCommand(pData);
else
// take actions accordingly.
private void Transport_MessageReceived(object sender, MessageEventArgs e)
private void Transport_Disconnected(object sender, ServerEventArgs e)
this.mTcpClinet.ConnectToServer(this.mReconnect);
private void Transport_ConnectingSucceeded(object sender, ServerEventArgs e)
private void OnReceiveMessage(byte pData)
add a comment |Â
up vote
0
down vote
I would like to share a sample solution based on following aspects
- Client is only responsible for Sending, Receiving, Connecting and disconnecting from Server.
- Wrapper class is responsible for state management of Client, like initialization, dispose, re-connection, processing the received data, forwarding data to client, decision based on the connection state of Client with server
In this way you could able to reuse the Client and add have different wrapper classes based on the functionality like (Active-Active client, Active - Passive client, Broad cast clients)...
I would like to share the abstract code (doesn't have any DI or pattern implementation), you can modify according to your requirement.
public enum LinkStatus
Connected,
Disconnected
MessageEventArgs Event args raised by client, during the sending and reception of message to server, which includes the data and status.
public class MessageEventArgs : EventArgs
public byte Message get; private set;
public bool Result get; private set;
public int Index get; private set;
public MessageEventArgs(int pIndex, byte pData, bool pResult)
Message = pData;
Result = pResult;
Index = pIndex;
ServerEventArgs Event args class holding server details
public class ServerEventArgs : EventArgs
public IPAddress IP get; private set;
public int Port get; private set;
public int Index get; private set;
public ServerEventArgs(int pIndex, IPEndPoint pServerEndPoint)
this.IP = pServerEndPoint.Address;
this.Port = pServerEndPoint.Port;
this.Index = pIndex;
MyTcpClient class is shown below, which will do following tasks
a. Expose methods to start and stop communication with server
b. Expose Connection Link status
c. Raise events like MessageSentSuccessfully, MessageSendingFailed, Disconnected, ConnectingSucceeded, MessageReceived.
public class MyTcpClient
private int mIndex;
private LinkStatus mConnectionStatus = LinkStatus.Disconnected;
private Socket mClientSocket = null;
private NetworkStream mNetworkStream = null;
private BackgroundWorker mBwReceiver;
private IPEndPoint mServerEP = null;
private IPEndPoint mClientEP = null;
private Semaphore mSendSemaphore;
private int mConnectionSleepTime = 5000;
public MyTcpClient(int pIndex, string pServerAddress, int pPortNumber)
this.mIndex = pIndex;
this.mSendSemaphore = new Semaphore(1, 1);
IPAddress address = IPAddress.Parse(pServerAddress);
IPEndPoint endPoint = new IPEndPoint(address, pPortNumber);
this.mServerEP = endPoint;
this.mClientEP = new IPEndPoint(IPAddress.Any, 0);
this.mSendSemaphore = new Semaphore(1, 1);
public event EventHandler<MessageEventArgs> MessageReceived;
public event EventHandler<MessageEventArgs> MessageSent;
public event EventHandler<MessageEventArgs> MessageSendingFailed;
public event EventHandler<ServerEventArgs> Disconnected;
public event EventHandler<ServerEventArgs> ConnectingSucceeded;
public LinkStatus ConnectionStatus
get
if (this.mConnectionStatus == LinkStatus.Connected)
bool result = false;
try
if (this.mClientSocket != null)
result = !(this.mClientSocket.Poll(1, SelectMode.SelectRead) && this.mClientSocket.Available == 0);
catch
if (result)
this.mConnectionStatus = LinkStatus.Connected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
return this.mConnectionStatus;
public void ConnectToServer(int pSleepingInterval)
this.mConnectionSleepTime = pSleepingInterval;
BackgroundWorker bwConnector = new BackgroundWorker();
bwConnector.DoWork += new DoWorkEventHandler(this.BwConnector_DoWork);
bwConnector.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwConnector_RunWorkerCompleted);
bwConnector.RunWorkerAsync();
public void SendCommand(byte pMessage)
if (this.ConnectionStatus == LinkStatus.Connected)
BackgroundWorker bwSendWorker = new BackgroundWorker();
bwSendWorker.DoWork += new DoWorkEventHandler(this.BwSendWorker_DoWork);
bwSendWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwSendWorker_RunWorkerCompleted);
bwSendWorker.WorkerSupportsCancellation = true;
bwSendWorker.RunWorkerAsync(pMessage);
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, pMessage, false));
public void DisconnectFromServer(bool pCanRaise)
try
if (this.ConnectionStatus == LinkStatus.Connected)
try
this.mBwReceiver.CancelAsync();
this.mBwReceiver.Dispose();
catch
try
this.mClientSocket.Shutdown(SocketShutdown.Both);
this.mClientSocket.Close();
catch
finally
this.mClientSocket = null;
this.SocketDisconnected(pCanRaise);
protected virtual void OnMessageReceived(MessageEventArgs e)
if (this.MessageReceived != null)
this.MessageReceived(this, e);
protected virtual void OnMessageSent(MessageEventArgs e)
if (this.MessageSent != null)
this.MessageSent(this, e);
protected virtual void OnMessageSendingFailed(MessageEventArgs e)
if (this.MessageSendingFailed != null)
this.MessageSendingFailed(this, e);
protected virtual void OnServerDisconnected(ServerEventArgs e)
this.DisconnectFromServer(true);
protected virtual void OnConnectionSucceeded()
this.mConnectionStatus = LinkStatus.Connected;
if (this.ConnectingSucceeded != null)
this.ConnectingSucceeded(this, new ServerEventArgs(this.mIndex, this.mServerEP));
protected virtual void OnConnectingFailed()
this.DisconnectFromServer(true);
private void BwConnector_DoWork(object sender, DoWorkEventArgs e)
bool result = false;
try
Thread.Sleep(this.mConnectionSleepTime);
this.mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.mClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.mClientSocket.Bind(this.mClientEP);
// thread gets block until it gets response for server
this.mClientSocket.Connect(this.mServerEP);
result = true;
//// catch generic exception
catch
result = false;
e.Result = result;
private void BwConnector_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
//// raise connection fail event if client not connected to server
if (!(bool)e.Result)
this.OnConnectingFailed();
else
this.mNetworkStream = new NetworkStream(this.mClientSocket);
this.mBwReceiver = new BackgroundWorker();
this.mBwReceiver.WorkerSupportsCancellation = true;
this.mBwReceiver.DoWork += new DoWorkEventHandler(this.BwReceiver_DoWork);
this.mBwReceiver.RunWorkerAsync();
this.OnConnectionSucceeded();
((BackgroundWorker)sender).Dispose();
// catch generic exception if any thing happens, this is for safe
catch
private void BwReceiver_DoWork(object sender, DoWorkEventArgs e)
while (this.ConnectionStatus == LinkStatus.Connected && (this.mNetworkStream != null))
try
if (this.mNetworkStream.CanRead)
byte data = new byte[1024];
int noOfBytesRead = 0;
noOfBytesRead = this.mNetworkStream.Read(data, 0, data.Length);
if (noOfBytesRead > 0)
byte receivedData = new byte[noOfBytesRead];
Array.Copy(data, receivedData, receivedData.Length);
MessageEventArgs mArgs = new MessageEventArgs(this.mIndex, receivedData, true);
this.OnMessageReceived(mArgs);
else
catch
break;
this.OnServerDisconnected(new ServerEventArgs(this.mIndex, this.mServerEP));
private void BwSendWorker_DoWork(object sender, DoWorkEventArgs e)
byte sendData = (byte)e.Argument;
MessageEventArgs args = null;
//// check for connectivity
if (this.ConnectionStatus == LinkStatus.Connected && sendData.Length > 0)
try
this.mSendSemaphore.WaitOne();
this.mNetworkStream.Write(sendData, 0, sendData.Length);
this.mNetworkStream.Flush();
this.mSendSemaphore.Release();
args = new MessageEventArgs(this.mIndex, sendData, true);
e.Result = args;
//// catch generic exception, for safe
catch
args = new MessageEventArgs(this.mIndex, sendData, false);
this.mSendSemaphore.Release();
e.Result = args;
else
args = new MessageEventArgs(this.mIndex, sendData, false);
e.Result = args;
private void BwSendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
MessageEventArgs args = e.Result as MessageEventArgs;
if (args != null)
// raised when message is sent to server successfully
if ((!e.Cancelled && e.Error == null) && (bool)args.Result)
this.OnMessageSent(new MessageEventArgs(this.mIndex, args.Message, args.Result));
// raised when message sending is failed to server
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, args.Message, args.Result));
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, null, false));
((BackgroundWorker)sender).Dispose();
catch
public void SocketDisconnected(bool pCanRaise)
this.mConnectionStatus = LinkStatus.Disconnected;
if (this.Disconnected != null && pCanRaise)
this.Disconnected(this, new ServerEventArgs(this.mIndex, this.mServerEP));
MyTCPWrapper class is show below, which will do the following
a. Controls the life cycle of MyTCPClients, based on the connection status and message reception status.
b. Add multiple clients, to provide redundencies like (Active - Active, Active - Passive)...
public class MyTcpWrapper
private MyTcpClient mTcpClinet = null;
private bool mTransportConnectionStatus = false;
private int mReconnect = 10;
public int Reconnect
get
return this.mReconnect;
set
this.mReconnect = value;
public bool TransportConnectionStatus
get
bool result = false;
if(this.mTcpClinet != null)
if(this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
result = true;
return result;
public void InitializeTransport()
if (this.DeInitializeTransport())
this.mTcpClinet = new MyTcpClient(1, "serverAddress", 9000);
this.mTcpClinet.ConnectingSucceeded += new EventHandler<ServerEventArgs>(Transport_ConnectingSucceeded);
this.mTcpClinet.Disconnected += new EventHandler<ServerEventArgs>(Transport_Disconnected);
this.mTcpClinet.MessageReceived += new EventHandler<MessageEventArgs>(Transport_MessageReceived);
this.mTcpClinet.ConnectToServer(this.Reconnect);
public bool DeInitializeTransport()
bool result = true;
this.mReconnect = 0;
try
if (this.mTcpClinet != null)
this.mTcpClinet.MessageReceived -= this.Transport_MessageReceived;
this.mTcpClinet.Disconnected -= this.Transport_Disconnected;
this.mTcpClinet.ConnectingSucceeded -= this.Transport_ConnectingSucceeded;
this.mTcpClinet.DisconnectFromServer(false);
catch
finally
this.mTcpClinet = null;
return result;
public void SendData(byte pData)
if (this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
this.mTcpClinet.SendCommand(pData);
else
// take actions accordingly.
private void Transport_MessageReceived(object sender, MessageEventArgs e)
private void Transport_Disconnected(object sender, ServerEventArgs e)
this.mTcpClinet.ConnectToServer(this.mReconnect);
private void Transport_ConnectingSucceeded(object sender, ServerEventArgs e)
private void OnReceiveMessage(byte pData)
add a comment |Â
up vote
0
down vote
up vote
0
down vote
I would like to share a sample solution based on following aspects
- Client is only responsible for Sending, Receiving, Connecting and disconnecting from Server.
- Wrapper class is responsible for state management of Client, like initialization, dispose, re-connection, processing the received data, forwarding data to client, decision based on the connection state of Client with server
In this way you could able to reuse the Client and add have different wrapper classes based on the functionality like (Active-Active client, Active - Passive client, Broad cast clients)...
I would like to share the abstract code (doesn't have any DI or pattern implementation), you can modify according to your requirement.
public enum LinkStatus
Connected,
Disconnected
MessageEventArgs Event args raised by client, during the sending and reception of message to server, which includes the data and status.
public class MessageEventArgs : EventArgs
public byte Message get; private set;
public bool Result get; private set;
public int Index get; private set;
public MessageEventArgs(int pIndex, byte pData, bool pResult)
Message = pData;
Result = pResult;
Index = pIndex;
ServerEventArgs Event args class holding server details
public class ServerEventArgs : EventArgs
public IPAddress IP get; private set;
public int Port get; private set;
public int Index get; private set;
public ServerEventArgs(int pIndex, IPEndPoint pServerEndPoint)
this.IP = pServerEndPoint.Address;
this.Port = pServerEndPoint.Port;
this.Index = pIndex;
MyTcpClient class is shown below, which will do following tasks
a. Expose methods to start and stop communication with server
b. Expose Connection Link status
c. Raise events like MessageSentSuccessfully, MessageSendingFailed, Disconnected, ConnectingSucceeded, MessageReceived.
public class MyTcpClient
private int mIndex;
private LinkStatus mConnectionStatus = LinkStatus.Disconnected;
private Socket mClientSocket = null;
private NetworkStream mNetworkStream = null;
private BackgroundWorker mBwReceiver;
private IPEndPoint mServerEP = null;
private IPEndPoint mClientEP = null;
private Semaphore mSendSemaphore;
private int mConnectionSleepTime = 5000;
public MyTcpClient(int pIndex, string pServerAddress, int pPortNumber)
this.mIndex = pIndex;
this.mSendSemaphore = new Semaphore(1, 1);
IPAddress address = IPAddress.Parse(pServerAddress);
IPEndPoint endPoint = new IPEndPoint(address, pPortNumber);
this.mServerEP = endPoint;
this.mClientEP = new IPEndPoint(IPAddress.Any, 0);
this.mSendSemaphore = new Semaphore(1, 1);
public event EventHandler<MessageEventArgs> MessageReceived;
public event EventHandler<MessageEventArgs> MessageSent;
public event EventHandler<MessageEventArgs> MessageSendingFailed;
public event EventHandler<ServerEventArgs> Disconnected;
public event EventHandler<ServerEventArgs> ConnectingSucceeded;
public LinkStatus ConnectionStatus
get
if (this.mConnectionStatus == LinkStatus.Connected)
bool result = false;
try
if (this.mClientSocket != null)
result = !(this.mClientSocket.Poll(1, SelectMode.SelectRead) && this.mClientSocket.Available == 0);
catch
if (result)
this.mConnectionStatus = LinkStatus.Connected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
return this.mConnectionStatus;
public void ConnectToServer(int pSleepingInterval)
this.mConnectionSleepTime = pSleepingInterval;
BackgroundWorker bwConnector = new BackgroundWorker();
bwConnector.DoWork += new DoWorkEventHandler(this.BwConnector_DoWork);
bwConnector.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwConnector_RunWorkerCompleted);
bwConnector.RunWorkerAsync();
public void SendCommand(byte pMessage)
if (this.ConnectionStatus == LinkStatus.Connected)
BackgroundWorker bwSendWorker = new BackgroundWorker();
bwSendWorker.DoWork += new DoWorkEventHandler(this.BwSendWorker_DoWork);
bwSendWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwSendWorker_RunWorkerCompleted);
bwSendWorker.WorkerSupportsCancellation = true;
bwSendWorker.RunWorkerAsync(pMessage);
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, pMessage, false));
public void DisconnectFromServer(bool pCanRaise)
try
if (this.ConnectionStatus == LinkStatus.Connected)
try
this.mBwReceiver.CancelAsync();
this.mBwReceiver.Dispose();
catch
try
this.mClientSocket.Shutdown(SocketShutdown.Both);
this.mClientSocket.Close();
catch
finally
this.mClientSocket = null;
this.SocketDisconnected(pCanRaise);
protected virtual void OnMessageReceived(MessageEventArgs e)
if (this.MessageReceived != null)
this.MessageReceived(this, e);
protected virtual void OnMessageSent(MessageEventArgs e)
if (this.MessageSent != null)
this.MessageSent(this, e);
protected virtual void OnMessageSendingFailed(MessageEventArgs e)
if (this.MessageSendingFailed != null)
this.MessageSendingFailed(this, e);
protected virtual void OnServerDisconnected(ServerEventArgs e)
this.DisconnectFromServer(true);
protected virtual void OnConnectionSucceeded()
this.mConnectionStatus = LinkStatus.Connected;
if (this.ConnectingSucceeded != null)
this.ConnectingSucceeded(this, new ServerEventArgs(this.mIndex, this.mServerEP));
protected virtual void OnConnectingFailed()
this.DisconnectFromServer(true);
private void BwConnector_DoWork(object sender, DoWorkEventArgs e)
bool result = false;
try
Thread.Sleep(this.mConnectionSleepTime);
this.mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.mClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.mClientSocket.Bind(this.mClientEP);
// thread gets block until it gets response for server
this.mClientSocket.Connect(this.mServerEP);
result = true;
//// catch generic exception
catch
result = false;
e.Result = result;
private void BwConnector_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
//// raise connection fail event if client not connected to server
if (!(bool)e.Result)
this.OnConnectingFailed();
else
this.mNetworkStream = new NetworkStream(this.mClientSocket);
this.mBwReceiver = new BackgroundWorker();
this.mBwReceiver.WorkerSupportsCancellation = true;
this.mBwReceiver.DoWork += new DoWorkEventHandler(this.BwReceiver_DoWork);
this.mBwReceiver.RunWorkerAsync();
this.OnConnectionSucceeded();
((BackgroundWorker)sender).Dispose();
// catch generic exception if any thing happens, this is for safe
catch
private void BwReceiver_DoWork(object sender, DoWorkEventArgs e)
while (this.ConnectionStatus == LinkStatus.Connected && (this.mNetworkStream != null))
try
if (this.mNetworkStream.CanRead)
byte data = new byte[1024];
int noOfBytesRead = 0;
noOfBytesRead = this.mNetworkStream.Read(data, 0, data.Length);
if (noOfBytesRead > 0)
byte receivedData = new byte[noOfBytesRead];
Array.Copy(data, receivedData, receivedData.Length);
MessageEventArgs mArgs = new MessageEventArgs(this.mIndex, receivedData, true);
this.OnMessageReceived(mArgs);
else
catch
break;
this.OnServerDisconnected(new ServerEventArgs(this.mIndex, this.mServerEP));
private void BwSendWorker_DoWork(object sender, DoWorkEventArgs e)
byte sendData = (byte)e.Argument;
MessageEventArgs args = null;
//// check for connectivity
if (this.ConnectionStatus == LinkStatus.Connected && sendData.Length > 0)
try
this.mSendSemaphore.WaitOne();
this.mNetworkStream.Write(sendData, 0, sendData.Length);
this.mNetworkStream.Flush();
this.mSendSemaphore.Release();
args = new MessageEventArgs(this.mIndex, sendData, true);
e.Result = args;
//// catch generic exception, for safe
catch
args = new MessageEventArgs(this.mIndex, sendData, false);
this.mSendSemaphore.Release();
e.Result = args;
else
args = new MessageEventArgs(this.mIndex, sendData, false);
e.Result = args;
private void BwSendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
MessageEventArgs args = e.Result as MessageEventArgs;
if (args != null)
// raised when message is sent to server successfully
if ((!e.Cancelled && e.Error == null) && (bool)args.Result)
this.OnMessageSent(new MessageEventArgs(this.mIndex, args.Message, args.Result));
// raised when message sending is failed to server
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, args.Message, args.Result));
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, null, false));
((BackgroundWorker)sender).Dispose();
catch
public void SocketDisconnected(bool pCanRaise)
this.mConnectionStatus = LinkStatus.Disconnected;
if (this.Disconnected != null && pCanRaise)
this.Disconnected(this, new ServerEventArgs(this.mIndex, this.mServerEP));
MyTCPWrapper class is show below, which will do the following
a. Controls the life cycle of MyTCPClients, based on the connection status and message reception status.
b. Add multiple clients, to provide redundencies like (Active - Active, Active - Passive)...
public class MyTcpWrapper
private MyTcpClient mTcpClinet = null;
private bool mTransportConnectionStatus = false;
private int mReconnect = 10;
public int Reconnect
get
return this.mReconnect;
set
this.mReconnect = value;
public bool TransportConnectionStatus
get
bool result = false;
if(this.mTcpClinet != null)
if(this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
result = true;
return result;
public void InitializeTransport()
if (this.DeInitializeTransport())
this.mTcpClinet = new MyTcpClient(1, "serverAddress", 9000);
this.mTcpClinet.ConnectingSucceeded += new EventHandler<ServerEventArgs>(Transport_ConnectingSucceeded);
this.mTcpClinet.Disconnected += new EventHandler<ServerEventArgs>(Transport_Disconnected);
this.mTcpClinet.MessageReceived += new EventHandler<MessageEventArgs>(Transport_MessageReceived);
this.mTcpClinet.ConnectToServer(this.Reconnect);
public bool DeInitializeTransport()
bool result = true;
this.mReconnect = 0;
try
if (this.mTcpClinet != null)
this.mTcpClinet.MessageReceived -= this.Transport_MessageReceived;
this.mTcpClinet.Disconnected -= this.Transport_Disconnected;
this.mTcpClinet.ConnectingSucceeded -= this.Transport_ConnectingSucceeded;
this.mTcpClinet.DisconnectFromServer(false);
catch
finally
this.mTcpClinet = null;
return result;
public void SendData(byte pData)
if (this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
this.mTcpClinet.SendCommand(pData);
else
// take actions accordingly.
private void Transport_MessageReceived(object sender, MessageEventArgs e)
private void Transport_Disconnected(object sender, ServerEventArgs e)
this.mTcpClinet.ConnectToServer(this.mReconnect);
private void Transport_ConnectingSucceeded(object sender, ServerEventArgs e)
private void OnReceiveMessage(byte pData)
I would like to share a sample solution based on following aspects
- Client is only responsible for Sending, Receiving, Connecting and disconnecting from Server.
- Wrapper class is responsible for state management of Client, like initialization, dispose, re-connection, processing the received data, forwarding data to client, decision based on the connection state of Client with server
In this way you could able to reuse the Client and add have different wrapper classes based on the functionality like (Active-Active client, Active - Passive client, Broad cast clients)...
I would like to share the abstract code (doesn't have any DI or pattern implementation), you can modify according to your requirement.
public enum LinkStatus
Connected,
Disconnected
MessageEventArgs Event args raised by client, during the sending and reception of message to server, which includes the data and status.
public class MessageEventArgs : EventArgs
public byte Message get; private set;
public bool Result get; private set;
public int Index get; private set;
public MessageEventArgs(int pIndex, byte pData, bool pResult)
Message = pData;
Result = pResult;
Index = pIndex;
ServerEventArgs Event args class holding server details
public class ServerEventArgs : EventArgs
public IPAddress IP get; private set;
public int Port get; private set;
public int Index get; private set;
public ServerEventArgs(int pIndex, IPEndPoint pServerEndPoint)
this.IP = pServerEndPoint.Address;
this.Port = pServerEndPoint.Port;
this.Index = pIndex;
MyTcpClient class is shown below, which will do following tasks
a. Expose methods to start and stop communication with server
b. Expose Connection Link status
c. Raise events like MessageSentSuccessfully, MessageSendingFailed, Disconnected, ConnectingSucceeded, MessageReceived.
public class MyTcpClient
private int mIndex;
private LinkStatus mConnectionStatus = LinkStatus.Disconnected;
private Socket mClientSocket = null;
private NetworkStream mNetworkStream = null;
private BackgroundWorker mBwReceiver;
private IPEndPoint mServerEP = null;
private IPEndPoint mClientEP = null;
private Semaphore mSendSemaphore;
private int mConnectionSleepTime = 5000;
public MyTcpClient(int pIndex, string pServerAddress, int pPortNumber)
this.mIndex = pIndex;
this.mSendSemaphore = new Semaphore(1, 1);
IPAddress address = IPAddress.Parse(pServerAddress);
IPEndPoint endPoint = new IPEndPoint(address, pPortNumber);
this.mServerEP = endPoint;
this.mClientEP = new IPEndPoint(IPAddress.Any, 0);
this.mSendSemaphore = new Semaphore(1, 1);
public event EventHandler<MessageEventArgs> MessageReceived;
public event EventHandler<MessageEventArgs> MessageSent;
public event EventHandler<MessageEventArgs> MessageSendingFailed;
public event EventHandler<ServerEventArgs> Disconnected;
public event EventHandler<ServerEventArgs> ConnectingSucceeded;
public LinkStatus ConnectionStatus
get
if (this.mConnectionStatus == LinkStatus.Connected)
bool result = false;
try
if (this.mClientSocket != null)
result = !(this.mClientSocket.Poll(1, SelectMode.SelectRead) && this.mClientSocket.Available == 0);
catch
if (result)
this.mConnectionStatus = LinkStatus.Connected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
else
this.mConnectionStatus = LinkStatus.Disconnected;
return this.mConnectionStatus;
public void ConnectToServer(int pSleepingInterval)
this.mConnectionSleepTime = pSleepingInterval;
BackgroundWorker bwConnector = new BackgroundWorker();
bwConnector.DoWork += new DoWorkEventHandler(this.BwConnector_DoWork);
bwConnector.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwConnector_RunWorkerCompleted);
bwConnector.RunWorkerAsync();
public void SendCommand(byte pMessage)
if (this.ConnectionStatus == LinkStatus.Connected)
BackgroundWorker bwSendWorker = new BackgroundWorker();
bwSendWorker.DoWork += new DoWorkEventHandler(this.BwSendWorker_DoWork);
bwSendWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwSendWorker_RunWorkerCompleted);
bwSendWorker.WorkerSupportsCancellation = true;
bwSendWorker.RunWorkerAsync(pMessage);
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, pMessage, false));
public void DisconnectFromServer(bool pCanRaise)
try
if (this.ConnectionStatus == LinkStatus.Connected)
try
this.mBwReceiver.CancelAsync();
this.mBwReceiver.Dispose();
catch
try
this.mClientSocket.Shutdown(SocketShutdown.Both);
this.mClientSocket.Close();
catch
finally
this.mClientSocket = null;
this.SocketDisconnected(pCanRaise);
protected virtual void OnMessageReceived(MessageEventArgs e)
if (this.MessageReceived != null)
this.MessageReceived(this, e);
protected virtual void OnMessageSent(MessageEventArgs e)
if (this.MessageSent != null)
this.MessageSent(this, e);
protected virtual void OnMessageSendingFailed(MessageEventArgs e)
if (this.MessageSendingFailed != null)
this.MessageSendingFailed(this, e);
protected virtual void OnServerDisconnected(ServerEventArgs e)
this.DisconnectFromServer(true);
protected virtual void OnConnectionSucceeded()
this.mConnectionStatus = LinkStatus.Connected;
if (this.ConnectingSucceeded != null)
this.ConnectingSucceeded(this, new ServerEventArgs(this.mIndex, this.mServerEP));
protected virtual void OnConnectingFailed()
this.DisconnectFromServer(true);
private void BwConnector_DoWork(object sender, DoWorkEventArgs e)
bool result = false;
try
Thread.Sleep(this.mConnectionSleepTime);
this.mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.mClientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.mClientSocket.Bind(this.mClientEP);
// thread gets block until it gets response for server
this.mClientSocket.Connect(this.mServerEP);
result = true;
//// catch generic exception
catch
result = false;
e.Result = result;
private void BwConnector_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
//// raise connection fail event if client not connected to server
if (!(bool)e.Result)
this.OnConnectingFailed();
else
this.mNetworkStream = new NetworkStream(this.mClientSocket);
this.mBwReceiver = new BackgroundWorker();
this.mBwReceiver.WorkerSupportsCancellation = true;
this.mBwReceiver.DoWork += new DoWorkEventHandler(this.BwReceiver_DoWork);
this.mBwReceiver.RunWorkerAsync();
this.OnConnectionSucceeded();
((BackgroundWorker)sender).Dispose();
// catch generic exception if any thing happens, this is for safe
catch
private void BwReceiver_DoWork(object sender, DoWorkEventArgs e)
while (this.ConnectionStatus == LinkStatus.Connected && (this.mNetworkStream != null))
try
if (this.mNetworkStream.CanRead)
byte data = new byte[1024];
int noOfBytesRead = 0;
noOfBytesRead = this.mNetworkStream.Read(data, 0, data.Length);
if (noOfBytesRead > 0)
byte receivedData = new byte[noOfBytesRead];
Array.Copy(data, receivedData, receivedData.Length);
MessageEventArgs mArgs = new MessageEventArgs(this.mIndex, receivedData, true);
this.OnMessageReceived(mArgs);
else
catch
break;
this.OnServerDisconnected(new ServerEventArgs(this.mIndex, this.mServerEP));
private void BwSendWorker_DoWork(object sender, DoWorkEventArgs e)
byte sendData = (byte)e.Argument;
MessageEventArgs args = null;
//// check for connectivity
if (this.ConnectionStatus == LinkStatus.Connected && sendData.Length > 0)
try
this.mSendSemaphore.WaitOne();
this.mNetworkStream.Write(sendData, 0, sendData.Length);
this.mNetworkStream.Flush();
this.mSendSemaphore.Release();
args = new MessageEventArgs(this.mIndex, sendData, true);
e.Result = args;
//// catch generic exception, for safe
catch
args = new MessageEventArgs(this.mIndex, sendData, false);
this.mSendSemaphore.Release();
e.Result = args;
else
args = new MessageEventArgs(this.mIndex, sendData, false);
e.Result = args;
private void BwSendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
try
MessageEventArgs args = e.Result as MessageEventArgs;
if (args != null)
// raised when message is sent to server successfully
if ((!e.Cancelled && e.Error == null) && (bool)args.Result)
this.OnMessageSent(new MessageEventArgs(this.mIndex, args.Message, args.Result));
// raised when message sending is failed to server
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, args.Message, args.Result));
else
this.OnMessageSendingFailed(new MessageEventArgs(this.mIndex, null, false));
((BackgroundWorker)sender).Dispose();
catch
public void SocketDisconnected(bool pCanRaise)
this.mConnectionStatus = LinkStatus.Disconnected;
if (this.Disconnected != null && pCanRaise)
this.Disconnected(this, new ServerEventArgs(this.mIndex, this.mServerEP));
MyTCPWrapper class is show below, which will do the following
a. Controls the life cycle of MyTCPClients, based on the connection status and message reception status.
b. Add multiple clients, to provide redundencies like (Active - Active, Active - Passive)...
public class MyTcpWrapper
private MyTcpClient mTcpClinet = null;
private bool mTransportConnectionStatus = false;
private int mReconnect = 10;
public int Reconnect
get
return this.mReconnect;
set
this.mReconnect = value;
public bool TransportConnectionStatus
get
bool result = false;
if(this.mTcpClinet != null)
if(this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
result = true;
return result;
public void InitializeTransport()
if (this.DeInitializeTransport())
this.mTcpClinet = new MyTcpClient(1, "serverAddress", 9000);
this.mTcpClinet.ConnectingSucceeded += new EventHandler<ServerEventArgs>(Transport_ConnectingSucceeded);
this.mTcpClinet.Disconnected += new EventHandler<ServerEventArgs>(Transport_Disconnected);
this.mTcpClinet.MessageReceived += new EventHandler<MessageEventArgs>(Transport_MessageReceived);
this.mTcpClinet.ConnectToServer(this.Reconnect);
public bool DeInitializeTransport()
bool result = true;
this.mReconnect = 0;
try
if (this.mTcpClinet != null)
this.mTcpClinet.MessageReceived -= this.Transport_MessageReceived;
this.mTcpClinet.Disconnected -= this.Transport_Disconnected;
this.mTcpClinet.ConnectingSucceeded -= this.Transport_ConnectingSucceeded;
this.mTcpClinet.DisconnectFromServer(false);
catch
finally
this.mTcpClinet = null;
return result;
public void SendData(byte pData)
if (this.mTcpClinet.ConnectionStatus == LinkStatus.Connected)
this.mTcpClinet.SendCommand(pData);
else
// take actions accordingly.
private void Transport_MessageReceived(object sender, MessageEventArgs e)
private void Transport_Disconnected(object sender, ServerEventArgs e)
this.mTcpClinet.ConnectToServer(this.mReconnect);
private void Transport_ConnectingSucceeded(object sender, ServerEventArgs e)
private void OnReceiveMessage(byte pData)
answered Apr 17 at 7:10
vishnu vardhan
1874
1874
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192251%2falways-stay-connected-mechanism-for-socket-connection%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
2
What actually makes you feeling wrong about what you're doing there?
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 17 at 1:01
Not wrong, just not very practical. It feels like I'm doing a lot of work to delegate a small job which can be done much easier, although I can't see a better way as of now.
â user692959239
Apr 17 at 1:07
2
Please post all code of this class.
â Heslacher
Apr 17 at 4:20