C# http listener not listening on localhost, only works with FQDN

Mathias Conradt picture Mathias Conradt · Apr 25, 2016 · Viewed 7.3k times · Source

(Please remove the close votes. IMHO this is a valid question, all necessary information is provided and yet tried to brief with all necessary information that's required to identify the possible source of the problem).

I'm new to C# coming from the Java world. I try to get a simple http server to listen on a port (in my case 8080) on localhost.

I followed this blog post https://codehosting.net/blog/BlogEngine/post/Simple-C-Web-Server.aspx.

When I run the program, it says

enter image description here

but I cannot reach http://localhost:8080/test/ via browser and netstat does not show port 8888 either. The port is also not blocked by firewall.

Generally, I can run other servers, such as Tomcat, on that port, without a problem. The port is not blocked or used by other applications when I run the C# http server program.

The code:

Program.cs:

static void Main(string[] args)
{
    WebServer ws = new WebServer();
    ws.Run();
    Console.WriteLine("A simple webserver. Press a key to quit.");
    Console.ReadKey();
    ws.Stop();  
}

WebServer.cs:

namespace WebServerTest
{
    public class WebServer
    {
        private readonly HttpListener _listener = new HttpListener();
        private readonly Func<HttpListenerRequest, string> _responderMethod;

        public WebServer()
        {
            if (!HttpListener.IsSupported)
                throw new NotSupportedException(
                    "Needs Windows XP SP2, Server 2003 or later.");

            _listener.Prefixes.Add("http://localhost:8080/test/");
            _responderMethod = SendResponse;
            _listener.Start();
        }

        public static string SendResponse(HttpListenerRequest request)
        {
            return string.Format("<HTML><BODY>My web page.<br>{0}</BODY></HTML>", DateTime.Now);
        }

        public void Run()
        {
            ThreadPool.QueueUserWorkItem((o) =>
            {
                Console.WriteLine("Webserver running...");

                    while (_listener.IsListening)
                    {
                        ThreadPool.QueueUserWorkItem((c) =>
                        {
                            var ctx = c as HttpListenerContext;

                            string rstr = _responderMethod(ctx.Request);
                            byte[] buf = Encoding.UTF8.GetBytes(rstr);
                            ctx.Response.ContentLength64 = buf.Length;
                            ctx.Response.OutputStream.Write(buf, 0, buf.Length);


                        }, _listener.GetContext());
                    }


            });
        }

        public void Stop()
        {
            _listener.Stop();
            _listener.Close();
        }
    }
}

=========== Update ===========

  • I changed the port to 8080
  • all try-catch-blocks in the code are removed
  • I made sure that the port is not an issue: I tested to run Tomcat servlet container on port 8080 and it works fine (of course, now it's stopped again)
  • Port 8080 is not blocked by any other application nor Firewall

This is what happens when I start the application:

netstat -na | find "8080"

C:\>netstat -na | find "8080"
  TCP    10.10.1.177:8080       0.0.0.0:0              LISTENING
  TCP    192.168.56.1:8080      0.0.0.0:0              LISTENING
  TCP    192.168.99.1:8080      0.0.0.0:0              LISTENING

I don't understand why nothing is listening at 0.0.0.0:8080 (as it is the case for example when I run Tomcat on port 8080), but on those other IPs.

However, I cannot access the http server via localhost...

enter image description here

..or when I try to access via those IP addresses, it's return a "Bad Request" response but not

enter image description here

I also tried other ports such as 7777 or higher ones 10888.

ipconfig:

C:\>ipconfig

Windows-IP-Konfiguration

Ethernet-Adapter Ethernet:

   Verbindungsspezifisches DNS-Suffix: mycompany.ch
   Verbindungslokale IPv6-Adresse  . : fe80::5511:3eb5:408a:2562%4
   IPv4-Adresse  . . . . . . . . . . : 10.10.1.177
   Subnetzmaske  . . . . . . . . . . : 255.255.254.0
   Standardgateway . . . . . . . . . : 10.10.0.1

Drahtlos-LAN-Adapter WiFi:

   Medienstatus. . . . . . . . . . . : Medium getrennt
   Verbindungsspezifisches DNS-Suffix: mycompany.ch

Ethernet-Adapter VirtualBox Host-Only Network:

   Verbindungsspezifisches DNS-Suffix:
   Verbindungslokale IPv6-Adresse  . : fe80::b4b0:6fc5:d0fc:1c77%24
   IPv4-Adresse  . . . . . . . . . . : 192.168.56.1
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Standardgateway . . . . . . . . . :

Ethernet-Adapter VirtualBox Host-Only Network #2:

   Verbindungsspezifisches DNS-Suffix:
   Verbindungslokale IPv6-Adresse  . : fe80::b0e6:32c8:fc0a:af52%25
   IPv4-Adresse  . . . . . . . . . . : 192.168.99.1
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Standardgateway . . . . . . . . . :

VirtualBox Adapters should not be a problem for that program, right?

=============

Just to compare it - running a Tomcat on port 8080 on my PC works fine, just like this:

C:\>netstat -na | find "8080"
  TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING
  TCP    [::]:8080              [::]:0                 LISTENING

enter image description here

=========== Update 2 ===========

I changed the hostname from localhost to the FQDN:

_listener.Prefixes.Add("http://devml-nb01-81.mycompany.ch:8080/test/");

This way it works.

enter image description here

But why would it not work via localhost (such as Tomcat?)

C:\>ping localhost

Ping wird ausgeführt für devml-nb01-81.mycompany.ch [::1] mit 32 Bytes Daten:
Antwort von ::1: Zeit<1ms
Antwort von ::1: Zeit<1ms
Antwort von ::1: Zeit<1ms
Antwort von ::1: Zeit<1ms

Ping-Statistik für ::1:
    Pakete: Gesendet = 4, Empfangen = 4, Verloren = 0
    (0% Verlust),
Ca. Zeitangaben in Millisek.:
    Minimum = 0ms, Maximum = 0ms, Mittelwert = 0ms

Answer

Ian Mercer picture Ian Mercer · Apr 26, 2016

Open an elevated command prompt and try

netsh http add urlacl url=http://+:8080/ user=EVERYONE

(You'll need to use the localized name for EVERYONE or the SID which is global.)

Applications that use HTTP.sys need reservations. You can read more about that here.

By the way, localhost is often problematic in other ways (e.g. some OAuth providers don't allow it). One way around that is to use one of the DNS names that has been mapped to 127.0.0.1 like vcap.me. You can put any name in front: foo.vcap.me and it resolves to 127.0.0.1.