C#でSystem.Net.HttpListenerを試す。

C# コンピュータ
C#

System.Net.HttpListenerを使うとWebサーバーが書けるとのことなので試してみたいと思います。

とりあえずMicrosoftのサンプルプログラムをConsoleプロジェクトで動かせるように書き換えて実行してみます。
HttpListener クラス (System.Net)
単純で、プログラムによって制御できる HTTP プロトコル リスナーを提供します。 このクラスは継承できません。
using System.Net;

class Prog
{
    static void Main()
    {
        // HTTPリスナーを生成
        HttpListener listener = new();
        // プレフィックスをセット
        listener.Prefixes.Add("http://localhost:8080/");
        // リスナーを開始
        listener.Start();
        Console.WriteLine("Listening...");
        // コンテキストを取得
        HttpListenerContext context = listener.GetContext();
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;

        // HTML文字列
        string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
        // HTML文字列⇒バイト配列
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
        // バイト配列の長さをセット
        response.ContentLength64 = buffer.Length;
        // 書き込み先ストリームを取得
        System.IO.Stream output = response.OutputStream;
        // 書き込み
        output.Write(buffer,0,buffer.Length);
        // 書き込みストリームをクローズ
        output.Close();
        // HTTPリスナーを停止
        listener.Stop();
    }
}

サーバー用のプログラムというとクライアントからのリクエストを待つため無限ループを書くイメージがあったのですが、サンプルプログラムではループらしき部分は存在しません。デバッグ実行したところコンソールにListening…と表示された後実行が一時停止していました。listener.GetContext();でクライアントからの入力待ちをしていると思われます。

その後listener.Prefixes.addで追加したURLにWebブラウザからアクセスしたところ、WebブラウザにHello world!が表示されました。デバック実行側を確認すると終了していました。

こちらのサンプルプログラムはリクエストを1件処理したら終了する流れになっています。実際サーバーとして動作させる場合、listener.Start()~listener.Stop()までの間をループするようにするとサーバーらしくリクエストを処理するようになると考えられます。また、シングルスレッドで動くことになりますが、こちらをマルチスレッドにするとパフォーマンスが向上しそうな予感がします。

また、リクエストに対しHello Worldを固定で返すプログラムになっていますが、リクエストに応じて異なる内容が返るように分岐処理が必要になると思われます。

例外が発生した場合、クライアントには404NotFoundや500Server Errorなどのメッセージを返しながらサーバー側にはスタックトレースなどの情報をログファイルに書き出す処理を行いながら、例外によってループが止まらないようなコードを書く必要がありそうです。

個人として本格的なWebサーバーを作る必要性は余り感じませんが、デスクトップアプリケーション内で動く簡易のWebサーバーを立ち上げてアプリケーションソフト内でHTTP通信するのも面白いかと思います。

コメント