Domanda

Sto provando a creare un semplice server web C # a cui, in questa fase, puoi accedere tramite il tuo browser e farò semplicemente un "Ciao Mondo".

Il problema che sto riscontrando è che il server può ricevere i dati correttamente - ottengo le informazioni di intestazione del browser - ma il browser non riceve nulla che invio. Inoltre, posso solo collegarmi al server andando su localhost (o 127.0.0.1). Non riesco ad accedervi andando al mio IP e non è un'impostazione di rete perché Apache funziona bene se lo eseguo invece. Inoltre, sto usando un programma di monitoraggio delle porte e dopo aver tentato una connessione da un browser, la porta del processo si blocca in uno stato TIME_WAIT anche se ho detto alla connessione di chiudersi e dovrebbe tornare a LISTEN.

Ecco il codice pertinente. Un paio di chiamate potrebbero non avere senso, ma questo è un pezzo di un programma più ampio.

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

Qualcuno ha qualche idea? Sembra che debba essere qualcosa di stupido da parte mia, ma non so proprio cosa. Gradirei davvero qualsiasi intuizione

È stato utile?

Soluzione

Potresti sapere che puoi utilizzare HttpListener per scrivere molto facilmente un web server di base - questo si occupa della maggior parte dei bit dolorosi, permettendoti di concentrarti sulla scrittura del codice reale. La pagina MSDN fornisce un esempio.

Nota che questo utilizza HTTP.SYS, il che è positivo, ma significa che i non amministratori devono avere esplicitamente accesso alle porte aperte; su xp puoi farlo con httpcfg ; su Vista puoi usare netsh . Vedi qui per ulteriori informazioni

Altri suggerimenti

Una cosa che al momento non è un problema, ma potrebbe essere successiva, è che la lunghezza del contenuto è basata sulla lunghezza Unicode della stringa del messaggio, non sul binario lunghezza.

C'è anche molto da fare nel costruttore di Connection - cose che in realtà non appartengono a un costruttore, IMO. Inoltre non chiude le cose se si verificano eccezioni.

Hai visto cosa succede in un tracciante di rete come WireShark? Sarebbe il modo più semplice per vedere se qualsiasi dati viene rispedito al client.

In alternativa, pubblica una versione breve ma completa del tuo codice che possiamo compilare ed eseguire noi stessi.

Forse mi manca qualcosa, ma il motivo per cui puoi connetterti solo su localhost è perché l'IP che stai ascoltando è 127.0.0.1, questo fa sì che TCPListener ascolti solo su quell'indirizzo IP. E non vedo da nessuna parte che stai chiamando qualsiasi disconnessione client, TCPListener è una chiamata bloccante, quindi rimane lì per sempre fino a quando non viene stabilita una connessione. Nella mia esperienza passata con TCP / IP e TCPListener, le classi TCPClient non c'è molto modo di forzare l'ascoltatore a rilasciare la sua connessione fino a quando non si rilascia la connessione client. La chiamata a TCPListener.Abort () non elimina la connessione client che mantiene bloccata la porta.

Per chiunque si trovi in ??una situazione simile in cui si desidera accedere al server C # dall'indirizzo IP della rete locale, sarà necessario ascoltare l'indirizzo 0.0.0.0 che significa ascoltare su tutti gli indirizzi IP non specifici come 127.0.0.1 ecc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top