Instance members of singleton object or static members of class - c#

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;
}
}
}

Related

Is there any way to check if socket connection is available?

I have the following code:
class MyServer
{
TcpListener myList;
Socket socket;
public MyServer(string ip)
{
this.myList = new TcpListener(ip, 12001);
this.myList.Start();
Thread t = new Thread(new ThreadStart(GetConnection));
t.Start();
}
public void GetConnection()
{
try
{
socket = myList.AcceptSocket(); //(1)
}
catch
{
Console.WriteLine("Error");
}
}
public void StopListening()
{
this.myList.Stop();
}
}
And it works well: I start the server, and if I "regret" I call StopListening() (before connection has been made!) and because I close myList, (1) is failing.
Is there any way to write this code without the try{}catch{} - rewrite GetConnection() as:
public void GetConnection()
{
while ( myList is open && there is no connection)
{
//do nothing
}
if (myList is open)
{
this.socket = myList.AcceptConnection();
}
}
or another way? Thanks.
socket = myList.AcceptSocket()
Is a blocking call, so it will throw an exception if the underlying socket stops Listening so you will need a try/catch anyway for that blocking call.
You could test:
if (myList.Server.IsBound)
{
this.socket = myList.AcceptConnection();
}
This way you wouldn't block for the next connection unless the socket was actively listening. But like I said if you want the program to be able to stop listening at some point, then this will still throw an exception when you call myList.Stop()

ObjectDisposedException on AcceptTcpClientAsync() for new TcpListener instance

I am stuck on a problem with the TcpListener class, after stopping the server and trying to start it again. What I am basically trying to do is to use the AcceptTcpClientAsync() method to process incoming connection requests and provide the possibility to restart the server.
Minimal Example:
class Program
{
private static TcpListener listener;
static void Main(string[] args)
{
StartServerAsync();
StopServer();
StartServerAsync();
Console.ReadKey();
}
private static void StopServer()
{
if (listener != null)
listener.Stop();
}
private async static void StartServerAsync()
{
listener = new TcpListener(IPAddress.Loopback, 1234);
listener.Start();
while (true)
{
var client = await listener.AcceptTcpClientAsync();
}
}
}
On the second call to await listener.AcceptTcpClientAsync() I am receiving an ObjectDisposedException for a socket.
Any idea or input how to overcome this problem?
Thanks!
Seems to be an unhealthy combination of static variables and async void. After doing some re-write to remove the static variable and use a factory method that returns the listener, the exception still occurs. But now I got it in the await call of the corresponding instance where Stop() has been called. This makes sense, cause the accept call has to return after stop, but it must signal that no client is available (which it does by throwing the exception).
So avoid async void, especially in combination with static members. Seems to be really toxic and sorry that I don't have any deeper explanation (except the link).
private static void Main(string[] args)
{
var listener1 = StartServerAsync(1234).Result;
StopServer(listener1);
var listener2 = StartServerAsync(1235).Result;
StopServer(listener2);
var listener3 = StartServerAsync(1236).Result;
StopServer(listener3);
Console.ReadKey();
}
private static void StopServer(TcpListener listener)
{
if (listener != null)
{
Console.WriteLine("Stop on port "+ listener.LocalEndpoint);
listener.Stop();
listener = null;
}
}
private static async Task<TcpListener> StartServerAsync(int port)
{
var listener = new TcpListener(IPAddress.Loopback, port);
listener.Start();
Console.WriteLine("Started on port " + port);
var task = Task.Run(async () => await WaitForConnection(listener));
await Task.Delay(100);
return listener;
}
private static async Task WaitForConnection(TcpListener listener)
{
while (true)
{
try
{
var client = await listener.AcceptTcpClientAsync();
}
catch (ObjectDisposedException)
{
Console.WriteLine("Failed on " + listener.LocalEndpoint);
}
}
}

Correct way to avoid a ObjectDisposedException, in this case?

I am currently getting an ObjectDisposedException on the following line.
var client = ((Socket) asyncResult.AsyncState).EndAccept(asyncResult);
System.ObjectDisposedException: 'Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.'
I was just wondering, what is the right way (in terms of best practice) to avoid an error like this? I'm unsure on how to handle it, how do I check if its disposed before hand, but is that what I should be doing? Or checking something else.
I'm self taught C# so I never learnt things like this, could someone give some insight?
Here is the full class:
internal sealed class SocketHandler : IDisposable
{
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
private readonly Socket _serverSocket;
public SocketHandler()
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Load();
}
public void Dispose()
{
_serverSocket?.Close(); // close also calls dispose...
}
private void Load()
{
var config = Program.Server.ConfigHandler;
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, config.GetConfigValueByKey("network.sockets.port").ToInt()));
_serverSocket.Listen(int.Parse(config.GetConfigValueByKey("network.sockets.backlog")));
_serverSocket.BeginAccept(OnAcceptConnection, _serverSocket);
}
private void OnAcceptConnection(IAsyncResult asyncResult)
{
try
{
if (_serverSocket == null)
{
return;
}
var client = ((Socket) asyncResult.AsyncState).EndAccept(asyncResult);
var playerHandler = Program.Server.BaseHandler.PlayerHandler;
var players = playerHandler.Players;
var config = Program.Server.ConfigHandler;
var maxConnections = int.Parse(config.GetConfigValueByKey("game.players.limit"));
var maxConnectionsPerIp = int.Parse(config.GetConfigValueByKey("game.players.ip_limit"));
if (players.Count >= maxConnections)
{
Logger.Warn("Incoming connection was refused because the player limit was exceeded.");
client.Shutdown(SocketShutdown.Both);
client.Close();
return;
}
if (players.Values.Count(x => x != null && !x._disconnected && x.getIp() == client.RemoteEndPoint.ToString().Split(':')[0]) > maxConnectionsPerIp)
{
Logger.Warn("Incoming connection was refused because the IP limit was exceeded.");
client.Shutdown(SocketShutdown.Both);
client.Close();
return;
}
var clientId = Randomizer.Next(1, 10000);
Program.Server.BaseHandler.PlayerHandler.TryAddPlayer(clientId, new Player(clientId, client, new InitialPacketParser()));
}
catch (SocketException socketException)
{
Logger.Fatal(socketException, "Failed to accept socket connection.");
}
finally
{
_serverSocket?.BeginAccept(OnAcceptConnection, _serverSocket);
}
}
}
As far as I understand the reference source a Socket does not Dispose itself. So, since your _serverSocket is private, you are the only one to control when it is disposed.
Your OnAcceptConnection() method already started to try to check that, but not completely.
In your Dispose() method (or any other place where you Close() or Dispose() your _serverSocket) you need to also set _serverSocket to null. You can do it like this in a thread-safe way:
public class SocketHandler
{
private Socket _serverSocket; // not read-only
/* ... */
public void Dispose()
{
Socket tmp = _serverSocket; // save instance
_serverSocket = null; // set field to null
tmp?.Close();
}
Now your OnAcceptConnection() returns when it checks if (_serverSocket == null) and you avoid the exception.
The problem might also come from how you are using SocketHandler in the first place. I can see nothing wrong with how the IDisposable pattern is implemented in your class. The normal way to avoid accessing a Disposable class after it has been disposed is wrapping it in a using statement which will auto-dispose the class after leaving the block:
using( SocketHandler handler = new SocketHandler())
{
(...)
} //handler will be disposed and not accessible after here
For more information on this Microsoft Docs has a good article explaining IDispose
EDIT:
Thanks for pointing out that I was on a completely wrong way to understand the question.
I at least recreated the scenario to best of my knowledge:
class Program
{
static void Main(string[] args)
{
using (C1 instance = new C1())
{
Task.Factory.StartNew(() =>
{
Task.Delay(1000);
bool disposed = (bool)typeof(C1).GetField("disposed", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(instance);
if (disposed)
{
Console.WriteLine("Already disposed will not call DoSomething()");
}
else
{
instance.DoSomething();
}
});
}
Console.ReadKey(true);
}
}
class C1 : IDisposable
{
bool disposed = false;
public C1()
{
}
public void DoSomething()
{
if (disposed)
throw new ObjectDisposedException("C1");
Console.WriteLine("Still existing!");
}
public void Dispose()
{
Dispose(true);
Console.WriteLine("Disposed!");
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
disposed = true;
}
}
And managed to workaround the exception with a reflection. Assuming that microsoft will have used the same pattern + namings as they are according to their Framework Design Guidelines this solution could at least be used as a workaround.
But I highly doubt that this the best way.

Adding Events to .NET Sockets in 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.

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

Categories

Resources