Slobodan Savkovic February 2016

.NET TcpListener Stop method does not stop the listener when there is a child process

I am working with some legacy TCP server code that works with sockets directly as it was written in .NET 2.0 and earlier. The server has a feature to 'stop' and 'start' accepting client connections.

To troubleshoot the issue I run the server in the console mode as admin user. On top of that I have eliminated the socket accept thread from the equation and all the code does is something like:

tcpListener = new TcpListener(IPAddress.Any, this.Port);
tcpListener.Start();

and

tcpListener.Stop();

This called from different methods. I have debugged the code and I am pretty sure the code executes only once. However, the issue is that call to Stop does not actually releases the socket address and subsequent call to Start therefore fails with the error "Only one usage of each socket address (protocol/network address/port) is normally permitted". I can also confirm from the ProcessExplorer that the server is still listening on the server port.

When I write a small console app that uses the same code snippets everything works fine. I have even tried tracing the .NET network and socket libraries, but there is no error or anything to indicate problems there.

It is not clear to me why call to Stop does not release the socket address?

Update: After more investigation it turns out that there is some strange effect of child process launch to the TcpListener. I have made a 'bare bone' sample code that illustrates the issue:

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;

namespace TcpListenerStartStop
{
    class MyTcpListener
    {
        public static void Main(string[] args)
        {
            Int32 port = 13000;

            if (args.Length > 0) // indicates child process
            {
                Thr        

Answers


Slobodan Savkovic February 2016

The real reason for this behavior is that TcpListener socket handle is inherited by the child process together with many other handles. Some discussions on the topic can be found here and here.

One obvious solution is to launch the child process before initializing TcpListener.

Another solution is to have UseShellExecute = true to avoid this socket handle inheritance.

Ideal solution would be to set socket handle option to prevent the inheritance by the child process, but I am not sure if this can be done in .NET.

Post Status

Asked in February 2016
Viewed 1,353 times
Voted 5
Answered 1 times

Search




Leave an answer