在Windows容器中使用命名管道(同一主机)

时间:2019-09-03 13:35:23

标签: docker containers ipc named-pipes windows-container

我想有2个Windows容器-通过命名管道(而不是匿名管道)在同一主机上运行(使用Windows 10客户端计算机和Windows的docker)。但是,我无法使其正常工作。

我的命名管道服务器类是here in GitHub。简而言之,这些代码来自Microsoft Docs:

    private  void ServerThread(object data)
    {
        NamedPipeServerStream pipeServer =
            new NamedPipeServerStream(this.pipeName, PipeDirection.InOut, numThreads);
        int threadId = Thread.CurrentThread.ManagedThreadId;
        pipeServer.WaitForConnection();
        try
        {
            StreamString ss = new StreamString(pipeServer);
            ss.WriteString("I am the one true server!");
            string message = ss.ReadString();

            ss.WriteString($"Server message {DateTime.Now.ToLongTimeString()}");
        }
        catch (IOException e)
        {
            Console.WriteLine("ERROR: {0}", e.Message);
        }
        pipeServer.Close();
    }

并且客户端代码(同样来自Microsoft Docs)位于同一GitHub repo中。基本上,代码如下:

    private static void RunCore(string ip, string pipeName)
    {
        NamedPipeClientStream pipeClient =
                new NamedPipeClientStream(ip, pipeName,
                    PipeDirection.InOut, PipeOptions.None,
                    TokenImpersonationLevel.Impersonation);
        pipeClient.Connect();

        StreamString ss = new StreamString(pipeClient);
        if (ss.ReadString() == "I am the one true server!")
        {
            ss.WriteString("Message from client " + DateTime.Now.ToString());
            Console.Write(ss.ReadString());
        }
        else
        {
            Console.WriteLine("Server could not be verified.");
        }
        pipeClient.Close();
    }

整个项目都在this GitHub directory中。

如果我现在在本地计算机上运行它,则客户端可以访问服务器(在客户端和服务器上都可以看到控制台消息)。然后,使用以下泊坞文件将可执行文件放入容器中:

FROM mcr.microsoft.com/dotnet/framework/runtime:4.8
WORKDIR /app
COPY ./bin/release/ ./
ENTRYPOINT ["C:\\app\\Namedpipe.exe"]

现在,在Windows 10客户端计算机(使用Windows Docker)上,我以以下方式启动服务器:

docker run -it -v \\.\pipe\helloworld:\\.\pipe\helloworld named-pipe-net-framework:latest

这时,我验证了主机中是否有一个命名管道(名称为“ helloworld”)(使用pipelist.exe)。然后我在客户端模式下用以下容器对容器进行午餐:

docker run -it -v \\.\pipe\helloworld:\\.\pipe\helloworld  named-pipe-net-framework:latest

但是客户端永远无法到达管道(这需要很长时间冻结,然后失败)。但是,我在客户端容器中使用了Powershell午餐(使用docker exec),并且可以运行pipelist.exe并看到可用的命名管道'helloworld'。但是代码不起作用。谁能给我一些指示,为什么这不起作用?

感谢进阶!

1 个答案:

答案 0 :(得分:1)

我发现只有客户端管道才能从容器内连接到主机上打开的服务器管道。

仅当我使用C ++ WIN32 API创建此类管道时,它对我也有效(使用.NET的NamedPipeClientStream时,冻结相同)。 无论使用哪种技术,在容器中创建服务器管道都会导致错误,这可能是因为容器中的映射已将其占用。

这实际上意味着一个人不能通过命名管道直接连接2个容器,因为这两个容器都是客户端管道,它们只能连接到主机上的服务器管道。

我相信Windows中命名管道的映射是通过在容器(服务器管道)和主机(客户端管道)上使用几个额外的管道实现的,并且消息通过4个连接的管道链传播:serverhost-clienthost-servercontainer-clientcontainer。

花了几天时间在互联网上搜索相同的信息,但没有运气。关于Windows容器中命名管道行为的几乎所有情况都是关于从容器内部访问Docker API。甚至可以开始怀疑它是否还能支持其他东西。