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()
Related
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);
}
}
}
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.
I'm writing a server in C# using the TCPListener class asynchronous. I currently have the following code as my network listener class:
public class NetworkListener
{
private readonly SessionController _sessions;
private readonly TcpListener _server;
public NetworkListener(KernelConfiguration configuration, SessionController sessions)
{
_server = new TcpListener(new IPEndPoint(IPAddress.Any, configuration.Network.port));
_server.Start();
_sessions = sessions;
}
public async Task StartAccepting(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
var client = await _server.AcceptTcpClientAsync();
Console.WriteLine($"New connection from {client.Client.RemoteEndPoint}.");
_sessions.AddSession(client, Guid.NewGuid(), out var session);
await session.StartReceiving();
}
Console.WriteLine("stop");
}
public void Dispose()
{
_server.Stop();
}
}
As my program.cs I have:
internal class Program
{
private static NetworkListener _networkListener;
private static CancellationTokenSource _cancellationTokenSource;
private static async Task Main(string[] args)
{
_networkListener = new NetworkListener(new KernelConfiguration(), new SessionController());
_cancellationTokenSource = new CancellationTokenSource();
var thread = new Thread(ProgressConsoleCommands);
thread.Start();
try
{
await _networkListener.StartAccepting(_cancellationTokenSource.Token);
}
finally
{
_networkListener.Dispose();
}
}
private static void ProgressConsoleCommands()
{
while (true)
{
var command = Console.ReadLine();
Console.WriteLine(command);
switch (command)
{
case "close":
Console.WriteLine("called");
_cancellationTokenSource.Cancel();
break;
}
}
}
}
What currently happens:
I start up my program. It starts the TcpListener. I can connect to the port the TcpListener is listening to. When I type in "close" (without the quotes of course), it writes "called". However, "stop" doesn't get written to the console and the TcpListener is still accepting new questions.
Desired state:
Whenever I type in "close", it should stop accepting new connections, write "stop" and be out of the loop. Then it should call the Dispose function of my NetworkListener class to stop the TcpListener completely and to dispose it.
You could try checking against TcpListener.Pending() within your while loop first, before invoking AcceptTcpClientAsync(), this way the loop would only block if there actually is a new connection to be handled.
https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.pending(v=vs.110).aspx
EDIT(0): you might want to add Thread.Sleep in the while loop if you do this, to minimise CPU load
EDIT(1): so what I was aiming at was something like this:
while (!token.IsCancellationRequested) {
if (_server.Pending()) {
var client = await _server.AcceptTcpClientAsync();
// insert code for handling new connection
}
Thread.Sleep(500);
}
The problem, as you described it, seems to be that "await AcceptTcpClientAsync()" blocks the while loop indefinitely, until a new client attempts to connect to the server.
As #Damien_The_Unbeliever pointed out in his comment, you could unblock it (in a dirty manner) by simply providing the TcpListener with a new client connection.
The above example should however - practically - execute the cancellation as soon as Thread.Sleep expires
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
I'm developing a windows service with .NET framework 4.0 and C#.
This service will open a socket to receive commands.
I have this socket listener class:
public class SocketListener
{
private System.Net.Sockets.TcpListener m_server;
public SQLServerSocketListener()
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 5445);
m_server = new System.Net.Sockets.TcpListener(ip);
}
public void Start()
{
m_server.Start();
m_server.BeginAcceptTcpClient(new AsyncCallback(Callback), m_server);
}
public void Stop()
{
if (m_server != null)
m_server.Stop();
}
private void Callback(IAsyncResult ar)
{
if (!(m_server.Server.IsBound) ||
(m_server.Server == null))
return;
TcpClient client;
try
{
client = m_server.EndAcceptTcpClient(ar);
}
catch (ObjectDisposedException)
{
//Listener canceled
return;
}
DataHandler dataHandler = new DataHandler(client);
ThreadPool.QueueUserWorkItem(dataHandler.HandleClient, client);
m_server.BeginAcceptTcpClient(new AsyncCallback(Callback), m_server);
}
}
And this class to process the commands received through the socket:
class DataHandler
{
private bool m_disposed = false;
private TcpClient m_controlClient;
private IPEndPoint m_remoteEndPoint;
private string m_clientIP;
private NetworkStream m_controlStream;
private StreamReader m_controlReader;
public DataHandler(TcpClient client)
{
m_controlClient = client;
}
public void HandleClient(object obj)
{
m_remoteEndPoint = (IPEndPoint)m_controlClient.Client.RemoteEndPoint;
m_clientIP = m_remoteEndPoint.Address.ToString();
m_controlStream = m_controlClient.GetStream();
m_controlReader = new StreamReader(m_controlStream, true);
string line;
try
{
while (((line = m_controlReader.ReadLine()) != null) ||
(m_controlClient == null) ||
(!m_controlClient.Connected))
{
CommandHandler.ProcessCommand(line);
}
}
catch (Exception ex)
{
Console.WriteLine("CodeServerService.DataHandler error: {0}", ex.Message);
}
finally
{
Dispose();
}
}
}
And, the CommandHandler:
class CommandHandler
{
public static void ProcessCommand(string command, string connStringINICIC, string connStringTRZIC, byte codeLevel)
{
switch (command)
{
case "GetNewCodes<EOF>":
CodesIncremental.GetNewCodes();
break;
}
}
}
And CodesIncremental:
public class CodesIncremental
{
public static bool GetNewCodes()
{
[ ... ]
}
}
My problem is that I can receive GetNewCodes<EOF> command before the first one finish. So, I need to don't let GetNewCodes<EOF>runs if there is another GetNewCodes<EOF> running.
How can I don't let run CodesIncremental.GetNewCodes(); if this code its running in another thread?
I need something to discard the commands received while CodesIncremental.GetNewCodes(); is running.
In pseudo code:
If CodesIncremental.GetNewCodes(); is running do nothing.
This version does not block. CompareExchange ensures atomicity, so only one thread will swap the value of the _running variable, the rest of threads will just return inmediately.
public class CodesIncremental
{
static Int32 _running = 0;
public static bool GetNewCodes()
{
if (Interlocked.CompareExchange(ref _running, 1, 0) == 1)
return false;
try
{
// Do stuff...
return true;
}
finally
{
_running = 0;
}
}
}
A difference than monitors or other synchronization methods, there is little contention on this method, and it is quite faster.
Maybe like this using AutoResetEvent:
public class CodesIncremental
{
private AutoResetEvent _event = new AutoResetEvent(true);
public static bool GetNewCodes()
{
if(!_event.WaitOne(0))
return true; //is running
try
{
/*
actions in case if isn't running
*/
}
finally
{
_event.Set();
}
return false;
}
}
EDIT: Update to address the modification of the question.
A simple way is to use the Monitor.TryEnter and Monitor.Exit
Just call the ExecuteGetNewCodeCommand for the processing of your "GetNewCode" command.
object _myLock = new object();
void ExecuteGetNewCodeCommand( ArgType args)
{
bool result = false;
try
{
result = Monitor.TryEnter(_myLock); // This method returns immediately
if( !result) // check if the lock is acquired.
return;
// Execute your command code here
}
finally
{
if(result) // release the lock.
Monitor.Exit(_myLock);
}
}
Old answer (before the modification of the question):
Think about using a queue and a Thread Pool.
Every time you receive a new Command (including "GetNewCode") insert it into a queue. In addition, you will have a Thread Pool that will read requests from the queue and execute them.
If you are using only one thread in the Thread pool, or a dedicated thread for this type of commands (where there are other threads for other requests/commands in the queue/queus), then only one "GetNewCode" request will be running at the same time.
This way you can control the number of threads your server will run. Thus, also the resources your server uses.
If you just synchronize (via locks or other mechanism) then there are a performance penalties. And maybe a denial of service, if you reached a thread limit. Let's say for somehow the execution of a request is taking too long (Maybe a deadlock in your code). If you will not use a Thread pool, and will execute the commands/requests on the same thread the client connected to your, then your sever may hang.
Though, If you will synchronize the threads inside the thread pool, then the server will not hang. Maybe it will be really slow to execute the requests, but it will still run and work.
There is a default .Net ThreadPool implementation at MSDN.
Add a lock to your CodesIncremental Class:
public class CodesIncremental
{
private object m_threadLock = new object();
public static bool GetNewCodes()
{
lock(m_threadLock)
{
[ ... ]
}
}
}
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
This way when your GetNewCodes method is called the first time the 'lock' statement will get an exclusive lock on the 'm_threadLock' object and only release it when the execution leaves the lock block, if any other thread calls the methods while the first thread is still inside the lock block it will not be able to get an exclusive lock and execution will suspend until it can.
Update:
Since you want to discard other calls try this:
public class CodesIncremental
{
private static object m_threadLock = new object();
private static bool m_running = false;
public static bool GetNewCodes()
{
lock(m_threadLock)
{
if(m_running)
{
return;
}
m_running = true;
}
try
{
[ ... ]
}
finally
{
m_running = false;
}
}
}
there might be better ways but this should do the trick.
Update 2: Hadn't seen the static