I am currently using TcpListener to address incoming connections, each of which are given a thread for handling the communication and then shutdown that single connection. Code looks as follows:
TcpListener listener = new TcpListener(IPAddress.Any, Port);
System.Console.WriteLine("Server Initialized, listening for incoming connections");
listener.Start();
while (listen)
{
// Step 0: Client connection
TcpClient client = listener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleConnection));
clientThread.Start(client.GetStream());
client.Close();
}
The listen
variable is a boolean that is a field on the class. Now, when the program shuts down I want it to stop listening for clients. Setting listen to false
will prevent it from taking on more connections, but since AcceptTcpClient
is a blocking call, it will at minimum take the next client and THEN exit. Is there any way to force it to simply break out and stop, right then and there? What effect does calling listener.Stop() have while the other blocking call is running?
Sockets provide powerful asynchronous capabilities. Take a look at Using an Asynchronous Server Socket
Here are couple of notes on the code.
Using manually created threads in this case may be an overhead.
The code below is subject to race conditions - TcpClient.Close() closes network stream you get through TcpClient.GetStream(). Consider closing client where you can definitely say that it is no longer needed.
TcpClient.Stop() closes underlying socket. TcpCliet.AcceptTcpClient() uses Socket.Accept() method on underlying socket which will throw SocketException once it is closed. You can call it from a different thread.
Anyway I recommend asynchronous sockets.
listener.Server.Close()
from another thread breaks the blocking call.See my answer here https://stackoverflow.com/a/17816763/2548170
TcpListener.Pending()
is not good solutionSome changes to make the Peter Oehlert anwer perfect. Because before 500 miliseconds the listener bloking again. To correct this:
Already mentioned above, use BeginAcceptTcpClient instead, it's much easier to manage asynchronously.
Here is some sample code :
Just to add even more reason to use the asynchronous approach, I'm pretty sure Thread.Abort won't work because the call is blocked in the OS level TCP stack.
Also... if you are calling BeginAcceptTCPClient in the callback to listen for every connection but the first, be careful to make sure that the thread that executed the initial BeginAccept doesn't terminate or else the listener will automatically get disposed by the framework. I suppose that's a feature, but in practice it's very annoying. In desktop apps it's not usually a problem, but on the web you might want to use the thread pool since those threads don't ever really terminate.