Question

J'essaie de créer un simple serveur Web C # auquel, à ce stade, vous pouvez accéder via votre navigateur et que vous ferez simplement un "Hello World".

Le problème que je rencontre est que le serveur peut recevoir des données correctement - je reçois les informations d'en-tête du navigateur - mais le navigateur ne reçoit rien de ce que j'envoie. De plus, je ne peux me connecter au serveur qu'en accédant à localhost (ou 127.0.0.1). Je ne peux pas y accéder en allant sur mon IP et ce n'est pas un paramètre de réseau car Apache fonctionne bien si je l'exécute à la place. De plus, j'utilise un programme de surveillance des ports et après avoir tenté une connexion à partir d'un navigateur, le port du processus est bloqué dans un état TIME_WAIT même si j'ai dit à la connexion de se fermer et qu'elle devrait revenir à LISTEN.

Voici le code correspondant. Quelques appels pourraient ne pas avoir de sens, mais il s’agit d’un élément d’un programme plus vaste.

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

Quelqu'un a-t-il des idées? C'est comme si ça devait être quelque chose de stupide de ma part mais je ne sais pas quoi. J'apprécierais vraiment toute idée

Était-ce utile?

La solution

Vous voudrez peut-être savoir que vous pouvez utiliser le HttpListener pour écrire un serveur Web de base très facilement - cela traite la plupart des éléments pénibles, vous permettant de vous concentrer sur l'écriture du code lui-même. La page MSDN en donne un exemple.

Notez que cela utilise HTTP.SYS, ce qui est bien - mais cela signifie que les non-administrateurs doivent explicitement avoir accès aux ports ouverts; sur xp, vous pouvez le faire avec httpcfg ; sur vista, vous pouvez utiliser netsh . Voir ici pour plus d'informations.

Autres conseils

Une chose qui ne pose pas de problème pour le moment mais qui pourrait l’être plus tard est que la longueur de votre contenu est basée sur la longueur Unicode de la chaîne de message, et non sur le fichier binaire longueur.

Il y a aussi beaucoup de choses dans le constructeur Connection - des choses qui n’appartiennent vraiment pas à un constructeur, IMO. Cela ne ferme pas non plus les choses si des exceptions se produisent.

Avez-vous examiné ce qui se passe dans un traceur de réseau tel que WireShark? Ce serait le moyen le plus simple de vérifier si des données sont renvoyées au client.

Vous pouvez également publier une version courte mais complète de votre code que nous pouvons compiler et exécuter nous-mêmes.

Peut-être qu'il me manque quelque chose, mais la seule raison pour laquelle vous pouvez vous connecter sur localhost est que l'adresse IP que vous écoutez est 127.0.0.1, TCPListener n'écoute donc que sur cette adresse IP. Et je ne vois nulle part où vous appelez un client déconnecté, TCPListener étant un appel bloquant, il reste donc indéfiniment jusqu'à ce qu'une connexion soit établie. Dans mon expérience passée avec les classes TCP / IP et TCPListener, TCPClient, il n’existait aucun moyen de forcer l’auditeur à abandonner sa connexion tant que la connexion cliente n’a pas été abandonnée. L'appel de TCPListener.Abort () ne supprime pas la connexion client qui maintient le port bloqué.

Si vous souhaitez accéder à votre serveur C # à partir de l'adresse IP du réseau local dans une situation similaire, vous devrez écouter l'adresse 0.0.0.0, ce qui signifie que vous devez écouter toutes les adresses IP et non une adresse spécifique comme 127.0.0.1, etc.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top