Go と C# を名前付きパイプでつなぐ

昨日、UNIXドメインソケットをGoで使うサンプルを作成したがその際にパフォーマンス比較用に作成した名前付きパイプを使ってC#と通信する。

サーバーサイド(Go言語)

特筆するところはない。

package main

import (
    "log"

    winio "github.com/Microsoft/go-winio"
)

var pipename = `\\.\pipe\winiotestpipe`
var ok = []byte("ok")
var bufSize = 65537

func main() {
    l, err := winio.ListenPipe(pipename, nil)
    if err != nil {
        return
    }
    defer l.Close()

    for {
        func() {
            conn, err := l.Accept()
            if err != nil {
                log.Fatal(err)
            }
            defer conn.Close()
            buf := make([]byte, bufSize)
            for {
                for {
                    n, err := conn.Read(buf)
                    if err != nil {
                        return
                    }
                    if buf[n-1] == '\n' {
                        break
                    }
                }
                conn.Write(ok)
            }
        }()
    }
}

クライアントサイド(C#)

注意するところは以下の通り * 名前付きパイプのパスをGo言語側と同じにする必要があるので、\\.\pipe\ 部分を削除しておく。 * UTF8でエンコードしてあげることで、GO側でも扱いやすくする。おそらくRead()したバッファは逆にUTF8からUTF16にエンコードする必要があるのではないかと思っているが、コード簡略化のため実施していない。

using System;
using System.IO.Pipes;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        static void PrintBuffer(byte[] buffer)
        {
            for (int i = 0; i < buffer.Length; i++)
            {
                Console.Write(Convert.ToChar(buffer[i]));
            }
        }

        static void PrintlnBuffer(byte[] buffer)
        {
            PrintBuffer(buffer);
            Console.WriteLine();
        }

        static void Main(string[] args)
        {
            var client = new NamedPipeClientStream("winiotestpipe");
            client.Connect();
            var enc = new UTF8Encoding();
            byte[] buffer = enc.GetBytes("a\n");
            int len = buffer.Length;

            PrintBuffer(buffer);
            client.Write(buffer, 0, len);
            client.Flush();

            byte[] rxbuf = new byte[2];
            client.Read(rxbuf, 0, 2);
            PrintlnBuffer(rxbuf);

            Console.ReadLine();
        }
    }
}

まとめ

jsonとかでやり取りしたらRPC通信的なことができてGoをバックエンドとしたデスクトップアプリとか書けるのかなぁ?と思っている。