Adding Events to .NET Sockets in C# - c#

I have a CustomSocket class that extends the Socket that adds events to get some feedback about clients disconnecting from a server. I am wondering how to add my client disconnect method to the event delegate if the _listenerSocket.Accept() method returns a Socket and not my CustomSocket class which has the events in it?? The code is as below.
public class CustomSocket : Socket
{
private readonly Timer timer;
private const int INTERVAL = 1000;
public delegate void SocketEventHandler(Socket socket);
public CustomSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) : base(addressFamily, socketType, protocolType)
{
timer = new Timer { Interval = INTERVAL };
timer.Elapsed += TimerTick;
}
public CustomSocket(SocketInformation socketInformation) : base(socketInformation)
{
timer = new Timer { Interval = INTERVAL };
timer.Elapsed += TimerTick;
}
private readonly List<SocketEventHandler> onCloseHandlers = new List<SocketEventHandler>();
public event SocketEventHandler SocketClosed
{
add { onCloseHandlers.Add(value); }
remove { onCloseHandlers.Remove(value); }
}
public bool EventsEnabled
{
set
{
if (value)
timer.Start();
else
timer.Stop();
}
}
private void TimerTick(object sender, EventArgs e)
{
if (!Connected)
{
foreach (var socketEventHandler in onCloseHandlers)
socketEventHandler.Invoke(this);
EventsEnabled = false;
}
}
// Hiding base connected property
public new bool Connected
{
get
{
bool part1 = Poll(1000, SelectMode.SelectRead);
bool part2 = (Available == 0);
if (part1 & part2)
return false;
else
return true;
}
}
}
I was thinking that I would want to add for events on the Socket that is returned from the Socket.Accept(); method except that this is a Socket is not a CustomSocket so there there are no events. I think I going about this the wrong way.
static void ListenThread()
{
try
{
for (; ; )
{
_listenerSocket.Listen(5);
_clients.Add(new ClientData(_listenerSocket.Accept()));
}
}
catch
{
//
}
}
I tried this
static void ListenThread()
{
try
{
for (; ; )
{
_listenerSocket.Listen(5);
CustomSocket cs = (CustomSocket) _listenerSocket.Accept();
_clients.Add(new ClientData(cs));
cs.SocketClosed += CsOnSocketClosed;
}
}
catch
{
//
}
}
But I get casting errors etc..
Any help would be appreciated..
Matt

You can't cast a Socket to a CustomSocket. Because Accept returns a Socket and not a CustomSocket.
You could wrap a Socket in a CustomSocket which takes a Socket as parameter like this to solve your issue.
class CustomSocket
{
private Socket _socket;
public Socket Socket
{
get
{
return _socket;
}
}
public CustomSocket(Socket s)
{
_socket = s;
}
}

You definitely need to use composition instead of inheritance for this, due to the fact that the Accept() method will never return an instance of your own class. See existing socket wrappers like TcpClient, NetworkStream, etc. for inspiration. There's not enough detail here to be able to provide specific guidance as to how to compose your Socket instance. However, for dealing with the Accept() method scenario specifically, it would look something like this:
class CustomSocket
{
private Socket _socket;
public CustomSocket(Socket socket)
{
_socket = socket;
}
public CustomSocket Accept()
{
return new CustomSocket(_socket.Accept());
}
}
Finally, it's not entirely clear what the overall goal in sub-classing/wrapping the Socket class here is, but the code you posted so far looks like you are trying to abstract a polling mechanism on the Socket class.
But polling a Socket is the least efficient way to use it, and is unnecessary. You may find that by using the asynchronous model with the Socket (e.g. Socket.BeginAccept(), ...BeginRead(), etc.) that you don't need to abstract anything, and that you can use the Socket class directly.

Related

C# TcpSockets Do I disconnect the clean/proper way?

So i know there are a lot of articles out there on this topic and i did read a lot of them i would say but for some reason im sure my code is not doing what it is supposed to do.
I want to close a connection between my Server and my Client.
Now on the serverside i start the disconnect with this code
public void shutdown()
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
And on the Client side i have some troubles understanding how i get to the disconnect what i believe is happening is the following: in my async receive callback i should get an error since the server started a shutdown sequence and i have to handle that (right???) so my code for the client looks like this:
ReceiveCallback:
private void ReceiveCallback(IAsyncResult result)
{
int bytesRecieved = 0;
byte[] tempBuff;
//Try to receive But if a Socket error occures disconnect otherwise start Receiving again
try
{
bytesRecieved = _socket.EndReceive(result);
}
catch (SocketException sockEx)
{
Disconnect(sockEx);
return;
}
catch (ObjectDisposedException disposeEx)
{
Disconnect(disposeEx);
return;
}
catch (Exception ex)
{
StartReceive();
return;
}
if (bytesRecieved == 0)
{
StartReceive();
return;
}
tempBuff = new byte[bytesRecieved];
Buffer.BlockCopy(_buffer, 0, tempBuff, 0, bytesRecieved);
StartReceive();
_packHandler.handlePacket(tempBuff);
}
Disconnect:
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
DisconnectCallback
private void DisconnectCallback(IAsyncResult result)
{
_socket.EndDisconnect(result);
_socket.Close();
}
(The Disconnect Method is overloaded so if i get an exception it puts up a messageBox and then also calls Disconnect. Just so i know what happened.)
Where am i wrong and what can i improve uppon ???
I tried the code and it seemed to work but i then looked with netstat if all sockets are closed and the client socket was not. It was in FIN_WAIT_2 which means that it (or the server???) did not yet send the FIN packet right ?
Oh and then i tried it again with this line changed:
if (bytesRecieved == 0)
{
StartReceive();
return;
}
TO
if (bytesRecieved == 0)
{
Disconnect;
return;
}
which then threw an exception on the serverside and on the clientside the client said that the connection was closed by the server ???
EDIT: Even when i have closed both Programs Netstat still shows the port in a WAITING status. what does that tell me ?
Your normal disconnect has a shutdown which will clear the socket so it can disconnect properly but your async style never calls shutdown. I added it in a convenient location below.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.Shutdown(SocketShutdown.Both); // Make sure to do this
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
EDIT:
From the sounds of it you don't have a reason to be using the Async Method? The async methods are so you can send data in a separate execution thread freeing up your thread to do some data processing for instance while that occurs.
I don't see any processing going on so I suggest you change disconnect like this and see if it resolves the problem. Because I don't think you are waiting on the Async methods which will not work out well.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
shutdown(); //Your standard disconnect that you showed up top. Scoping might be required.
}
A bit of data on Async can be scrounged up here: http://msdn.microsoft.com/en-us/library/38dxf7kt(v=vs.110).aspx
Important is:
If a server starts a shutdown sequence you DO have to handle it
Both sides have to call shutdown on their socket
You need a way to notice the disconnect (it does not give you an error, or least it didnt for me)
Therefor I created my own class customSocket which inherits from Socket
public class customSocket : Socket
{
#region Properties
private readonly Timer _timer;
private const int _interval = 1000;
private bool Connected
{
get
{
bool part1 = Poll(1000, SelectMode.SelectRead);
bool part2 = (Available == 0);
if (part1 && part2)
return false;
else
return true;
}
}
public bool EventsEnabled
{
set
{
if (value)
{
_timer.Start();
}
else
_timer.Stop();
}
}
#endregion
#region Constructors
public customSocket(AddressFamily addressFamily, SocketType sockType, ProtocolType protocolType)
: base(addressFamily, sockType, protocolType)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
public customSocket(SocketInformation sockInfo)
: base(sockInfo)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
#endregion
#region Events
public event EventHandler<EventArgs> Socket_disconected;
public void Raise_Socket_disconnected()
{
EventHandler<EventArgs> handler = Socket_disconected;
if (handler != null)
{
handler(this,new EventArgs());
}
}
private void TimerTick(object sender, EventArgs e)
{
if (!Connected)
{
Raise_Socket_disconnected();
}
}
#endregion
}
This version of a socket has an Event for a disconnect.
Now if you create an instance of your socket class you have to connect the handler and set the EventsEnabled true.
This handler then calls the shutdown and your socket does not stay in FIN_WAIT_2

Instance members of singleton object or static members of class

I am writing a listener class which creates a single HttpListener on random
unused port and listens on it. I tried to make it singleton. However I am
finding it difficult to keep that singleton object null when listening
to random HTTP port fails 10 times.
(I have shown port number and HttpListener instance as members of singleton
instance. However there are many other members that I have not shown for
simplicity.) This is my code:
class Listener
{
private static Listener listener = null; //singleton instance
//member variables
private HttpListener httpListener = null;
private int port = -1;
static Listener()
{
listener = new Listener();
}
private Listener()
{
try
{
port = //randomly generate
httpListener = new HttpListener();
//start listening
}
catch(Exception ex)
{
//cant listen on randomly chosen port
listener = null;
httpListener = null;
port = -1;
return;
}
}
}
However inside catch(), listener = null sets listener to null
just for a while. When default constructor returns it returns a new
instance of Listener, thus listener inside static constructor always have
instance assigned to it. Thus instead of listener = null inside default
constructor it should be this = null which is invalid.
Thus I moved the whole code inside static constructor. But that forcesd me to
Either make instance members (port and httpListener) static or
or use listener.port , listener.httpListener everywhere
class Listener
{
private static Listener listener = null; //singleton instance
//member variables
private HttpListener httpListener = null;
private int port = -1;
static Listener()
{
listener = new Listener();
try
{
listener.port = //randomly generate
listener.httpListener = new HttpListener();
//start listening
}
catch(Exception ex)
{
//cant listen on randomly chosen port
listener = null;
return;
}
}
private Listener()
{
}
}
I dont understand
Q1 whether to make port & httpListener static? (This I feel somewhat against OOP principles) or
Q2 whether to keep them as instance members and use listener. everywhere? (This is problematic since there are many such members and methods in my actual code and I have to attach listener. everywhere)
Or I am thinking it all wrong and should have followed different approach?
The immediate problem is that on failure the instance constructor is setting the static member listener to null. However, control then returns to the static constructor which sets the static member listener to the object that was created in the instance constructor. Hence, the behaviour you're seeing.
I'd argue that your (instance) constructor is trying to do too much. I would move the 'start listening' logic into a separate method and call that from anywhere other than the instance constructor. That will make your error handling a little easier e.g.
class Listener
{
public static Listener listener = null; //singleton instance
//member variables
private HttpListener httpListener = null;
private int port = -1;
static Listener GetListener()
{
if (listener != null)
{
return listener;
}
try
{
listener = new Listener();
listener.StartListening();
return listener;
}
catch (Exception)
{
//cant listen on randomly chosen port
listener.Cleanup();
listener = null;
throw;
}
}
private Listener()
{
port = RandomlyGenerate();
httpListener = new HttpListener();
}
private void StartListening()
{
//start listening
}
private void Cleanup()
{
httpListener.Close();
httpListener = null;
port = -1;
}
}
As BartoszKP mentions in the comments, you would probably be better of with a factory pattern here.
If you are interested in having a common place for events you could place that event in the factory class, or implement a static event in the Listener class.
public class ListenerFactory {
public IListener CreateListener(URI uri, int port) {
Listener l = new Listener();
l.MessageReceived += OnMessageReceived;
// do whatever with l. loop until connection, or use l.Start() for instance
return l;
}
public static event EventHandler<MessageEventArgs> ListenerMessageReceived;
private static void OnMessageReceived(object sender, MessageEventArgs e) {
// trigger ListenerMessageReceived
}
}
public interface IListener {
event EventHandler<MessageEventArgs> MessageReceived;
void Send(byte[] data);
}
public class Listener : IListener {
// implement interface
}
Then you just call new ListenerFactory().Create(host, port); when you need a new Listener, and if you want to listen for all messages, you subscribe to ListenerFactory.MessageReceived for incoming messages.
Using this pattern, you can create several connections at once instead of relying on one class to handle all of them.
You should move the initialization code of httpListener to its own method in order to avoid recreating listener. By doing that, and adding a property for getting the listener instance, classes can use Listener.Instance.Start() to reconnect if the static constructor fails to connect.
public class Listener
{
private static Listener listener = null; //singleton instance
//member variables
private HttpListener httpListener = null;
private int port = -1;
static Listener()
{
listener = new Listener();
// start listener
try {
listener.Start();
}
catch { }
}
// Use this method in other classes to start listener if it fails
// in static constructor
public static Listener Instance { get { return listener; } }
private Listener()
{
}
public bool IsConnected {
get { return httpListener != null; }
}
public void Start()
{
if (IsConnected) { return; }
try
{
port = //randomly generate
httpListener = new HttpListener();
//start listening
}
catch(Exception ex)
{
//cant listen on randomly chosen port
httpListener = null;
port = -1;
return;
}
}
}

How to get back to function from timed event

Okay so I have a function called readSensor which you guessed it.. reads a sensor.
But the sensors usually take about 100ms to respond. So in the readSensor function I am basically just starting a timer.
On the timed event I read the serialport and get my response.
However this means that my response is in the onTimedEvent when I want it to be in the readSensor function..
Basically from the main form I want to be able to do this.
value = readSensor()
when at the minute all I can do is readSensor() and then I can see the response is coming back by displaying it in a messagebox once the timedEvent fires.
here is my code. (I have missed out loads of serialport setup and stuff but hopefully you can see the problem I am in)
I don't want to just wait in the function for 100ms though polling the timer as that will make my program slow..
I want to somehow get the response back to the readSensor function and then back to the form.
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Timers;
namespace readSensor
{
public partial class readSens : UserControl
{
public readSens()
{
InitializeComponent();
}
private System.Timers.Timer rTimer;
SerialPort sp = new SerialPort();
private void setupTimer()
{
// Create a timer with a 100ms response.
rTimer = new System.Timers.Timer(100);
rTimer.SynchronizingObject = this;
// Hook up the Elapsed event for the timer.
rTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
string response = getResponse();
}
public string getResponse()
{
string status = "";
byte[] readBuffer = new byte[255];
if (sp.IsOpen)
{
if (sp.BytesToRead > 0) //there is data to read
{
int length = sp.BytesToRead;
for (int i = 0; i < length; i++)
{
readBuffer[i] = (byte)sp.ReadByte();
status = "pass";
return status;
}
}
}
public void readSensor(byte addr)
{
if (!sp.IsOpen)
{
openPort();
readSensor(addr); // calls itself again once port is opened
}
else if (sp.IsOpen)
{
rTimer.Start();
}
else
{
MessageBox.Show("Port not opened yet");
}
}
}
}
In the main form I am basically just saying
setupTimer();
readSensor();
on a button click.
I don't think you can do it without some callback mechanism. You could implement a while loop but that is not eficient as it would introduce spinning.
My advice is to implement a proper async pattern or something simple like:
ReadSensor(addr, DoSomethingWithResult);
public void DoSomethingWithResult(string result)
{
Console.WriteLine (result);
}
public partial class ReadSens : UserControl
{
private Action<string> _responseCallback;
public void ReadSensor(byte addr, Action<string> responseCallback)
{
_responseCallback = responseCallback;
// initiate timer
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
string response = getResponse();
_responseCallback(response);
}
}
Start a separate thread, then from that thread write into a queue the results back in your main thread.
class Game1
{
//We declare a queue, which is like an array that we can extract and enter data easily in a FIFO (first in, first out) style list.
Queue<string> q = new Queue<string>();
public void threadStart(object obj)
{
//We get the result of your function, while our main function is still looping and waiting.
string result = readInput()
//We tell C# that the parameter we passed in, is in fact the Game1 class passed from "t.Start"
Game1 game = (Game1)obj;
//This puts our "result" into the queue.
game.q.Enqueue(result);
}
public void start()
{
//Declares a new thread, which will run "threadStart" function.
System.Threading.Thread t = new System.Threading.Thread(threadStart);
//We start the other thread (that will run in parallel) and pass "this" as the parameter.
t.Start(this);
//We loop over and over, sleeping, whilst the other function runs at the same time. This is called "multi- threading"
while (q.Count == 0)
{
System.Threading.Thread.Sleep(10);
}
//This gets the last-entered (oldest) value from the queue q.
string result = q.Deque();
}
}
So this sets off a thread to get the result, and then in my version, polls the queue for a while until the results come back, but in yours could do a bunch of stuff, as long as you check the queue every now and again for new data.
Edit: Added commenting to hopefully alleviate some of your questions.
Could be this approach a valid solution for you? I think you only are using Timer to wait the serialPort to be open, but it can be self-controlled with raising event.
public class SensorReader
{
private Sensor sensor;
private string lastResponse;
public SensorReader(SerialPort serialPort)
{
this.serialPort = aSerialPort.
this.sensor = new Sensor(serialPort);
this.sensor.PortOpen += PortOpenEventHandler(OnPortOpen);
}
private void OnPortOpen()
{
this.ReadPort();
}
public string ReadPort(byte address)
{
if (!this.sensor.IsOpen)
{
this.sensor.OpenPort();
this.lastResponse = "The serial port doesn't respond... yet!";
}
else
{
// Read response at this point.
this.lastResponse = this.GetResponse();
}
return this.lastResponse;
}
}
public class Sensor
{
private SerialPort serialPort;
public Sensor(SerialPort aSerialPort)
{
this.serialPort = aSerialPort;
}
public bool IsOpen
{
get { return this.serialPort.IsOpen; }
}
public delegate void PortOpenEventHandler(object sender, EventArgs e);
public event PortOpenEventHandler PortOpen;
public void OpenPort()
{
// Open port here...
// ... and throw the PortOpen event.
if (this.PortOpen != null)
{
this.PortOpen(this, EventArgs.Empty);
}
}
}

"Unconnected" async socket prevents application shutdown

I wrote a small c# class to check for TCP connectivity (connection to TCP socket succeeds), using BeginConnect(). It appears to work well, IF the endpoint in question is available and the TCP session is actually connected.
However, when the endpoint is not listening and the connection times out, something weird happens: The class keeps "hanging" for about 15 to 20 seconds. Which coincides with the default timeout value.
However, I call socket.Close() when the timeout triggers - Which is said by MSDN to cancel all async operations.
Why does the class prevent the application from shutting down, when the connection does not succeed? What am I doing wrong?
public class CheckTCP
{
#region "Member Variables"
// socket connect timeout value
private int _timeout = 2000;
// check complete event
public event EventHandler<CheckCompletedEventArgs> CheckCompleted;
// perform TCP connect check
public void PerformCheck(EndPoint Socket)
{
StateObject state = new StateObject();
state.Me = this;
state.WorkSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
state.TimeoutTimer = new Timer();
state.TimeoutTimer.Interval = _timeout;
state.TimeoutTimer.Elapsed += (sender, e) => timeout_elapsed(sender, e, state);
state.TimeoutTimer.Start();
state.WorkSocket.SendTimeout = _timeout;
state.WorkSocket.ReceiveTimeout = _timeout;
state.WorkSocket.BeginConnect(Socket, new AsyncCallback(ConnectCallback), state);
}
// connection callback
private static void ConnectCallback(IAsyncResult ar)
{
StateObject state = (StateObject) ar.AsyncState;
state.TimeoutTimer.Stop();
state.TimeoutTimer.Dispose();
CheckCompletedEventArgs ea = new CheckCompletedEventArgs();
if (state.WorkSocket.Connected)
{
state.WorkSocket.EndConnect(ar);
state.WorkSocket.Close();
ea.Success = true;
state.Me.OnCheckCompleted(ea);
}
else
{
ea.Success = false;
state.Me.OnCheckCompleted(ea);
}
state.WorkSocket.Dispose();
state.Me = null;
}
// timeout callback
private void timeout_elapsed(object sender, EventArgs e, StateObject state)
{
state.TimeoutTimer.Stop();
state.WorkSocket.Close();
}
#endregion
// raiseevent helper
protected virtual void OnCheckCompleted(CheckCompletedEventArgs e)
{
// raise the event
EventHandler<CheckCompletedEventArgs> handler = CheckCompleted;
if (handler != null)
{
handler(this, e);
}
}
// checkcompleted event args class
public class CheckCompletedEventArgs : EventArgs
{
public bool Success { set; get; }
}
// async state object
public class StateObject
{
public EndPoint EndpointSocket { set; get; }
public Socket WorkSocket { set; get; }
public Timer TimeoutTimer { set; get; }
public CheckTCP Me { set; get; }
}
}

C# Check if socket is disconnected?

How can you check if a non-blocking socket is disconnect without using Poll?
Create a cusomt socket class inheriting .net socket class :
public delegate void SocketEventHandler(Socket socket);
public class CustomSocket : Socket
{
private readonly Timer timer;
private const int INTERVAL = 1000;
public CustomSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
: base(addressFamily, socketType, protocolType)
{
timer = new Timer { Interval = INTERVAL };
timer.Tick += TimerTick;
}
public CustomSocket(SocketInformation socketInformation)
: base(socketInformation)
{
timer = new Timer { Interval = INTERVAL };
timer.Tick += TimerTick;
}
private readonly List<SocketEventHandler> onCloseHandlers = new List<SocketEventHandler>();
public event SocketEventHandler SocketClosed
{
add { onCloseHandlers.Add(value); }
remove { onCloseHandlers.Remove(value); }
}
public bool EventsEnabled
{
set
{
if(value)
timer.Start();
else
timer.Stop();
}
}
private void TimerTick(object sender, EventArgs e)
{
if (!Connected)
{
foreach (var socketEventHandler in onCloseHandlers)
socketEventHandler.Invoke(this);
EventsEnabled = false;
}
}
// Hiding base connected property
public new bool Connected
{
get
{
bool part1 = Poll(1000, SelectMode.SelectRead);
bool part2 = (Available == 0);
if (part1 & part2)
return false;
else
return true;
}
}
}
Then use it like this :
var socket = new CustomSocket(
//parameters
);
socket.SocketClosed += socket_SocketClosed;
socket.EventsEnabled = true;
void socket_SocketClosed(Socket socket)
{
// do what you want
}
I have just implemented a Socket close event in each socket. so your application should register event handlers for this event. then socket will inform your application if it was closed itself ;)
if there was any problem with code, inform me.
The Socket class has a Connected property. According to MSDN the call to check is non-blocking. Is this not what you're looking for?

Categories

Resources