Pergunta

Eu estou tentando fazer um servidor web C # simples que, nesta fase, você pode acessar através de seu navegador e vai apenas fazer um "Olá Mundo".

O problema que estou tendo é que o servidor pode receber multa de dados - Recebo informações de cabeçalho do navegador - mas o navegador não recebe qualquer coisa que eu mandar. Além disso, só posso conectar ao servidor, indo para localhost (ou 127.0.0.1). Eu não posso chegar a ela, indo para o meu IP e não é uma configuração de rede porque Apache funciona bem se eu correr que em vez. Além disso, estou usando uma porta monitorando programa e depois de eu tentar uma conexão a partir de um navegador, a porta do processo fica preso em um estado TIME_WAIT mesmo que eu disse a conexão para perto e ele deve estar de volta a ouvir.

Aqui está o código relevante. Um par de chamadas pode não fazer sentido, mas este é um pedaço de um programa maior.

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);
    }
}

Alguém tem alguma idéia? Parece que ele tem que ser algo estúpido da minha parte, mas eu simplesmente não sei o que. Eu realmente aprecio qualquer visão

Foi útil?

Solução

Você pode gostar de saber que você pode usar HttpListener para escrever um web-servidor básico muito facilmente - trata-se de mais dos bits dolorosas, permitindo que você se concentrar em escrever o código real. A página MSDN dá um exemplo.

Note que esta HTTP.SYS usos, que é bom - mas significa que não-administradores precisam ser dado explicitamente o acesso a portas abertas; no XP, você pode fazer isso com httpcfg; no Vista você pode usar netsh. Veja aqui para mais.

Outras dicas

Uma coisa que não é um problema no momento, mas pode ser mais tarde é que o seu comprimento de conteúdo é baseado no Unicode comprimento da corda mensagem, não o binário comprimento.

Há também mais um monte acontecendo no construtor Connection - coisas que realmente não pertence a um construtor de todo, IMO. Ele também faz coisas não perto se ocorrerem exceções.

Você já olhou para o que está acontecendo em um marcador rede como Wireshark? Essa seria a maneira mais fácil de ver se qualquer de dados está sendo enviado de volta para o cliente.

Como alternativa, publicar uma versão curta, mas completa do seu código que pode compilar e executar a nós mesmos.

Talvez eu esteja apenas faltando alguma coisa, mas a razão que você só pode se conectar em localhost é porque o IP que você está escutando é 127.0.0.1, isso torna o TCPListener somente esperar por esse endereço IP. E eu não vejo qualquer lugar que você está chamando qualquer desconexão do cliente, o TCPListener é uma chamada de bloqueio, por isso fica lá para sempre até que uma conexão é feita. Na minha experiência passada com TCP / IP eo TCPListener, aulas TCPClient não há muito de uma maneira de forçar o ouvinte para soltá-lo da conexão até cair a conexão do cliente. Chamando TCPListener.Abort () não cai a conexão do cliente que mantém a porta bloqueada.

Para qualquer um em situação semelhante, onde você deseja acessar você C # servidor a partir do endereço IP da rede local, então você terá de ouvir endereço 0.0.0.0 significado escutar todos os endereços IP não um específico como 127.0.0.1 etc.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top