1

この段階では、ブラウザ経由でアクセスでき、「Hello World」を実行するだけの単純な C# Web サーバーを作成しようとしています。

私が抱えている問題は、サーバーがデータを正常に受信できることです-ブラウザーのヘッダー情報を取得します-しかし、ブラウザーは私が送信したものを何も受信しません。さらに、localhost (または 127.0.0.1) にアクセスすることによってのみ、サーバーに接続できます。自分の IP にアクセスしてもアクセスできません。これはネットワーク設定ではありません。代わりに Apache を実行すると、Apache が正常に動作するためです。また、ポート監視プログラムを使用していて、ブラウザーから接続を試みた後、接続を閉じるように指示したにもかかわらず、プロセスのポートが TIME_WAIT 状態でスタックし、LISTEN に戻るはずです。

関連するコードは次のとおりです。いくつかの呼び出しは意味をなさないかもしれませんが、これはより大きなプログラムの一部です。

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

誰にもアイデアはありますか?それは私の側で愚かなことをしなければならないように感じますが、私には何がわかりません. 洞察をいただければ幸いです

4

4 に答える 4

1

現時点では問題ではありませんが、後で問題になる可能性があることの1つは、コンテンツの長さがバイナリの長さではなく、メッセージ文字列のUnicodeの長さに基づいていることです。

また、Connectionコンストラクターでは、かなり多くのことが行われています。実際には、コンストラクターにまったく属していないもの、IMOです。また、例外が発生した場合でも、処理は終了しません。

WireSharkのようなネットワークトレーサーで何が起こっているかを見たことがありますか?これは、データがクライアントに返送されているかどうを確認する最も簡単な方法です。

または、自分でコンパイルして実行できる、短いが完全なバージョンのコードを投稿します。

于 2008-10-26T21:03:24.377 に答える
1

基本的なWebサーバーを非常に簡単に作成するために使用できることを知りたいと思うかもしれません。HttpListenerこれにより、ほとんどの面倒な部分を処理できるため、実際のコードの作成に集中できます。MSDNページに例があります。

これはHTTP.SYSを使用することに注意してください。これは優れていますが、管理者以外のユーザーに開いているポートへのアクセスを明示的に許可する必要があることを意味します。httpcfgxpでは、これを;で行うことができます。ビスタでは使用できますnetsh。詳細については、こちらをご覧ください。

于 2008-10-26T21:13:47.167 に答える
0

多分私は何かが欠けているだけかもしれませんが、あなたがリッスンしている IP が 127.0.0.1 であるため、localhost にしか接続できない理由は、TCPListener がその IP アドレスでのみリッスンするようにするためです。また、クライアントの切断を呼び出している場所はどこにもありません。TCPListener はブロッキング呼び出しであるため、接続が確立されるまで永遠にそこに留まります。TCP/IP と TCPListener、TCPClient クラスに関する私の過去の経験では、クライアント接続を切断するまで、リスナーにその接続を強制的に切断させる方法はほとんどありません。TCPListener.Abort() を呼び出しても、ポートがブロックされたままになるクライアント接続がドロップされません。

于 2008-10-26T21:26:14.067 に答える