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

标签 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 .

如果我现在在本地机器上运行它,客户端可以访问服务器(我在客户端和服务器中都看到控制台消息)。然后我使用以下 docker 文件将可执行文件放入容器中:
FROM mcr.microsoft.com/dotnet/framework/runtime:4.8
WORKDIR /app
COPY ./bin/release/ ./
ENTRYPOINT ["C:\\app\\Namedpipe.exe"]

现在,在 Windows 10 客户端机器上(使用 Docker for Windows),我将服务器启动为:
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”可用。但是代码不起作用。任何人都可以给我一些指示为什么这不起作用?

最佳答案

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

它也只在我使用 C++ WIN32 API 来创建这样的管道时(对我来说)有效,在使用 .NET 的 NamedPipeClientStream 时我有同样的卡住。
在容器中创建服务器管道,无论采用何种技术,都会导致错误,大概是因为它已经被容器中的映射占用了。

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

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

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

关于docker - 在 Windows 容器中使用命名管道(同一主机),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57772862/

相关文章:

C++ 泛型插入标准容器?

c++ - 在 C++ 中从文件中尽可能快地读取键值对

android - Binder 防止垃圾回收

docker - PHP-PM 容器不响应来自不同 Docker 容器的请求

Docker compose 文件版本兼容性错误

c# - 在 .NET core 下的 Linux 上运行 .NET 4.5

c# - 在 Mono 中处理通信的简单跨平台进程?

c - Node 和C应用程序之间的进程间通信

docker - 在Docker应用程序中保存和处理文件

c++ - 为什么我可以在本地使用 CMake 提供的模块(特别是 CMakeDependentOption.cmake),但不能在 CI 或 Docker 上使用?