Pregunta

Estoy tratando de hacer un servidor web C # simple al que, en esta etapa, puedas acceder a través de tu navegador y solo harás un " Hello World " ;.

El problema que tengo es que el servidor puede recibir una buena cantidad de datos (obtengo la información del encabezado del navegador), pero el navegador no recibe nada de lo que envío. Además, solo puedo conectarme al servidor yendo a localhost (o 127.0.0.1). No puedo conectarlo a mi IP y no es una configuración de red porque Apache funciona bien si lo ejecuto. Además, estoy usando un programa de monitoreo de puertos y, después de intentar una conexión desde un navegador, el puerto del proceso se atasca en un estado TIME_WAIT a pesar de que dije que la conexión se cerrara y debería volver a ESCUCHAR.

Aquí está el código relevante. Es posible que un par de llamadas no tengan sentido, pero esto es parte de un programa más grande.

class ConnectionHandler
{
    private Server server;

    private TcpListener tcp;

    private ArrayList connections;

    private bool listening;

    private Thread listeningThread;

    public Server getServer()
    {
        return server;
    }

    private void log(String s, bool e)
    {
        server.log("Connection Manager: " + s, e);
    }

    private void threadedListen()
    {
        while (listening)
        {
            try
            {
                TcpClient t = tcp.AcceptTcpClient();
                Connection conn = new Connection(this, t);
            }
            catch (NullReferenceException)
            {
                log("unable to accept connections!", true);
            }
        }
        log("Stopped listening", false);
    }

    public void listen()
    {
        log("Listening for new connections", false);
        tcp.Start();
        listening = true;
        if (listeningThread != null && listeningThread.IsAlive)
        {
            listeningThread.Abort();
        }
        listeningThread = new Thread(new ThreadStart(
            this.threadedListen));
        listeningThread.Start();
    }

    public void stop()
    {
        listening = false;
        if (listeningThread != null)
        {
            listeningThread.Abort();
            log("Forced stop", false);
        }
        log("Stopped listening", false);
    }

    public ConnectionHandler(Server server)
    {
        this.server = server;
        tcp = new TcpListener(new IPEndPoint(
            IPAddress.Parse("127.0.0.1"), 80));
        connections = new ArrayList();
    }
}

class Connection
{
    private Socket socket;
    private TcpClient tcp;

    private ConnectionHandler ch;

    public Connection(ConnectionHandler ch, TcpClient t)
    {
        try
        {
            this.ch = ch;
            this.tcp = t;
            ch.getServer().log("new tcp connection to " 
                + this.tcp.Client.RemoteEndPoint.ToString(), false);
            NetworkStream ns = t.GetStream();

            String responseString;
            Byte[] response;
            Int32 bytes;
            responseString = String.Empty;
            response = new Byte[512];
            bytes = ns.Read(response, 0, response.Length);
            responseString = 
                System.Text.Encoding.ASCII.GetString(response, 0, bytes);
            ch.getServer().log("Received: " + responseString);

            String msg = "<html>Hello World</html>";
            String fullMsg = "HTTP/1.x 200 OK\r\n"
                    + "Server: Test Server\r\n"
                    + "Content-Type: text/html; "
                        + "charset=UTF-8\r\n"
                    + "Content-Length: " + msg.Length + "\r\n"
                    + "Date: Sun, 10 Aug 2008 22:59:59 GMT"
                        + "\r\n";
            nsSend(fullMsg, ns);
            nsSend(msg, ns);

            ns.Close();
            tcp.Close();
        }
        catch (ArgumentNullException e)
        {
            ch.getServer().log("connection error: argument null exception: " + e);
        }
        catch (SocketException e)
        {
            ch.getServer().log("connection error: socket exception: " + e);
        }
    }

    private void nsSend(String s, NetworkStream ns)
    {
        Byte[] data = System.Text.Encoding.ASCII.GetBytes(s);
        ns.Write(data, 0, data.Length);
        ns.Flush();
        ch.getServer().log("Sent: " + s);
    }
}

¿Alguien tiene alguna idea? Siento que tiene que ser algo estúpido de mi parte, pero no sé qué. Realmente apreciaría cualquier idea

¿Fue útil?

Solución

Es posible que desee saber que puede usar HttpListener para escribir un servidor web básico con mucha facilidad, esto se ocupa de la mayoría de los bits dolorosos, lo que le permite concentrarse en escribir el código real. La página de MSDN da un ejemplo.

Tenga en cuenta que esto utiliza HTTP.SYS, lo cual es bueno, pero significa que los usuarios que no son administradores deben tener acceso explícito a los puertos abiertos; en xp puedes hacer esto con httpcfg ; en vista puedes usar netsh . Consulte aquí para obtener más información.

Otros consejos

Una cosa que no es un problema en este momento, pero podría ser más adelante es que la longitud de su contenido se basa en la longitud de Unicode de la cadena del mensaje, no en el binario longitud.

En el constructor de Connection también hay muchas cosas en marcha, cosas que realmente no pertenecen en absoluto a un constructor, IMO. Tampoco cierra las cosas si se producen excepciones.

¿Has visto lo que está pasando en un rastreador de red como WireShark? Esa sería la forma más fácil de ver si los datos de cualquier se envían de vuelta al cliente.

Alternativamente, publique una versión corta pero completa de su código que podamos compilar y ejecutar nosotros mismos.

Tal vez solo me esté faltando algo, pero la razón por la que solo puedes conectarte en localhost es porque la IP que estás escuchando es 127.0.0.1, esto hace que el TCPListener solo escuche en esa dirección IP. Y no veo ningún lugar al que esté llamando desconexión de un cliente, el TCPListener es una llamada de bloqueo, por lo que permanece ahí para siempre hasta que se establezca una conexión. En mi experiencia anterior con TCP / IP y TCPListener, las clases de TCPClient no son una forma de forzar al oyente a que desconecte su conexión hasta que usted abandone la conexión del cliente. Llamar a TCPListener.Abort () no interrumpe la conexión del cliente, lo que mantiene el puerto bloqueado.

Para cualquier persona en una situación similar en la que desee acceder a su servidor C # desde la dirección IP de la red local, deberá escuchar la dirección 0.0.0.0, lo que significa escuchar en todas las direcciones IP, no en una específica como 127.0.0.1, etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top