.NETで名前付きパイプを試す(3) - クライアントサーバ間で送受信する

前回に続いてもう少しNamedPipeClientStreamとNamedPipeServerStreamを使った名前付きパイプを試します。

ichiroku11.hatenablog.jp

今回はクライアント側のプログラムからサーバ側のプログラムにリクエストを送ってレスポンスを受け取るようにしてみます。クライアント側、サーバ側それぞれのプログラムの動きは次のようにしたいと思います。

クライアント側のプログラムの動き

  1. サーバに接続
  2. サーバにリクエストを送信する
  3. サーバからレスポンスを受信する

サーバ側のプログラムの動き

  1. クライアントからの接続を待つ
  2. クライアントからリクエストを受信する
  3. リクエストを処理してレスポンスを作る
  4. クライアントにレスポンスを送信する

これでちょっとはクライアントサーバっぽくなってくるかなと。

クライアント側のプログラム

まずはクライアント側からです。ReadObjectとWriteObject、Messageは前回のエントリで使ったものと同じです。またBinaryWriter、BinaryReaderのusingの部分でパイプのストリームを閉じないようにしています。

// クライアント側
class Program {
    private static async Task<Message> Client(Message request) {
        using (var stream = new NamedPipeClientStream("testpipe")) {
            // 1. サーバに接続
            await stream.ConnectAsync();

            // 2. サーバにリクエストを送信する
            Console.WriteLine($"{nameof(request)}: {request}");
            using (var writer = new BinaryWriter(stream, Encoding.UTF8, true)) {
                writer.WriteObject(request);
            }

            // 3. サーバからレスポンスを受信する
            var response = default(Message);
            using(var reader = new BinaryReader(stream, Encoding.UTF8, true)) {
                response = reader.ReadObject<Message>();
            }
            Console.WriteLine($"{nameof(response)}: {response}");

            return response;
        }
    }

    static void Main(string[] args) {
        Console.WriteLine("Client");

        Client(new Message {
            Id = 1,
            Content = "あいうえお",
        }).Wait();
    }
}

サーバ側のプログラム

続いてサーバ側です。リクエストからレスポンスを作る部分は、受け取ったリクエストの文字列をそのまま返すのも寂しいので文字列を逆順にしてレスポンスを作っています。

// サーバ側
class Program {
    private static async Task Server(Func<Message, Message> process) {
        using (var stream = new NamedPipeServerStream("testpipe")) {
            // 1. クライアントからの接続を待つ
            await stream.WaitForConnectionAsync();

            // 2. クライアントからリクエストを受信する
            var request = default(Message);
            using(var reader = new BinaryReader(stream, Encoding.UTF8, true)) {
                request = reader.ReadObject<Message>();
            }
            Console.WriteLine($"{nameof(request)}: {request}");

            // 3. リクエストを処理してレスポンスを作る
            var response = process(request);

            // 4. クライアントにレスポンスを送信する
            Console.WriteLine($"{nameof(response)}: {response}");
            using (var writer = new BinaryWriter(stream, Encoding.UTF8, true)) {
                writer.WriteObject(response);
            }
        }
    }

    // Contentの文字列を逆順にする処理
    private static Message Process(Message message) {
        return new Message {
            Id = message.Id,
            Content = new string(message.Content.Reverse().ToArray()),
        };
    }

    static void Main(string[] args) {
        Console.WriteLine("Server");

        Server(Process).Wait();
    }
}

実行する

2つのプログラムを実行すると送受信できることを確認できます。

// クライアント側の実行結果
Client
request: { Id = 1, Content = "あいうえお" }
response: { Id = 1, Content = "おえういあ" }

// サーバ側の実行結果
Server
request: { Id = 1, Content = "あいうえお" }
response: { Id = 1, Content = "おえういあ" }

今回も目的をクリアできたのでこのへんで。