如何将命名管道字符串从未管理的代码空间发送到托管代码空间? [英] How do you send a named pipe string from umnanaged to managed code space?

查看:24
本文介绍了如何将命名管道字符串从未管理的代码空间发送到托管代码空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎遇到了命名管道 101 问题.我有一个非常简单的设置来连接从 C++ 非托管应用程序传输到 C# 托管应用程序的单一命名管道.管道连接,但我无法通过管道发送消息",除非我关闭似乎刷新缓冲区并传递消息的句柄.好像消息被屏蔽了.我尝试颠倒客户端/服务器的角色并使用不同的标志组合调用它们,但没有任何运气.我可以轻松地从 C# 托管到 C++ 非托管的另一个方向发送消息.有没有人有任何见解.你们中的任何人都可以成功地将消息从 C++ 非托管发送到 C# 托管吗?我可以找到很多内部管理或非管理管道的示例,但没有管理到/来自未管理的内部管理 - 只是声称能够做到.

I appear to have a named pipes 101 issue. I have a very simple set up to connect a simplex named pipe transmitting from a C++ unmanaged app to a C# managed app. The pipe connects, but I cannot send a "message" through the pipe unless I close the handle which appears to flush the buffer and pass the message through. It's like the message is blocked. I have tried reversing the roles of client/server and invoking them with different Flag combinations without any luck. I can easily send messages in the other direction from C# managed to C++ unmanaged. Does anyone have any insight. Can any of you guys successfully send messages from C++ unmanaged to C# managed? I can find plenty of examples of intra amanged or unmanaged pipes but not inter managed to/from unamanged - just claims to be able to do it.

在清单中,为了清楚起见,我省略了很多包装材料.我认为相关的关键位是管道连接/创建/读写方法.不要太担心这里的阻塞/线程.

In the listings, I have omitted much of the wrapper stuff for clarity. The key bits I believe that are relevant are the pipe connection/creation/read and write methods. Don't worry too much about blocking/threading here.

C# 服务器端

    // This runs in its own thread and so it is OK to block
    private void ConnectToClient()
    {
        // This server will listen to the sending client
        if (m_InPipeStream == null)
        {
            m_InPipeStream =
                new NamedPipeServerStream("TestPipe", PipeDirection.In, 1);
        }

        // Wait for client to connect to our server
        m_InPipeStream.WaitForConnection();

        // Verify client is running
        if (!m_InPipeStream.IsConnected)
        {
            return;
        }

        // Start listening for messages on the client stream
        if (m_InPipeStream != null && m_InPipeStream.CanRead)
        {
            ReadThread = new Thread(new ParameterizedThreadStart(Read));
            ReadThread.Start(m_InPipeStream);
        }
    }


    // This runs in its own thread and so it is OK to block
    private void Read(object serverObj)
    {
        NamedPipeServerStream pipeStream = (NamedPipeServerStream)serverObj;
        using (StreamReader sr = new StreamReader(pipeStream))
        {
            while (true)
            {
                string buffer = "" ;
                try
                {
                    // Blocks here until the handle is closed by the client-side!!
                    buffer = sr.ReadLine();   // <<<<<<<<<<<<<<  Sticks here
                }
                catch
                {
                    // Read error
                    break;
                }

                // Client has disconnected?
                if (buffer == null || buffer.Length == 0)
                    break;

                // Fire message received event if message is non-empty
                if (MessageReceived != null && buffer != "")
                {
                    MessageReceived(buffer);
                }
            }
        }
    }

C++ 客户端

    // Static - running in its own thread.
    DWORD CNamedPipe::ListenForServer(LPVOID arg)
    {
        // The calling app (this) is passed as the parameter
        CNamedPipe* app = (CNamedPipe*)arg;

        // Out-Pipe: connect as a client to a waiting server
        app->m_hOutPipeHandle =
        CreateFile("\\.\pipe\TestPipe",
               GENERIC_WRITE,
               0,
               NULL,
               OPEN_EXISTING,
               FILE_ATTRIBUTE_NORMAL,
               NULL);
        // Could not create handle
        if (app->m_hInPipeHandle == NULL ||
            app->m_hInPipeHandle == INVALID_HANDLE_VALUE)
        {
            return 1;
        }

        return 0;
    }


    // Sends a message to the server
    BOOL CNamedPipe::SendMessage(CString message)
    {
    DWORD dwSent;

        if (m_hOutPipeHandle == NULL ||
            m_hOutPipeHandle == INVALID_HANDLE_VALUE)
        {
            return FALSE;
        }
        else
        {
            BOOL bOK =
                WriteFile(m_hOutPipeHandle,
                          message, message.GetLength()+1, &dwSent, NULL);
            //FlushFileBuffers(m_hOutPipeHandle);             // <<<<<<< Tried this
            return (!bOK || (message.GetLength()+1) != dwSent) ? FALSE : TRUE;
        }
    }


    // Somewhere in the Windows C++/MFC code...
    ...
    // This write is non-blocking. It just passes through having loaded the pipe.
    m_pNamedPipe->SendMessage("Hi de hi");
    ...

推荐答案

sr.ReadLine() 期望看到换行符以知道行尾.因为它既不接收新行也不接收流尾,它等待更多.试试:

sr.ReadLine() expects to see a newline character(s) to know the end of the line. Because it receives neither new-line nor end-of-stream, it waits for more. Try:

m_pNamedPipe->SendMessage("Hi de hi
")

或一些 sr.Read() 方法.

or some of the sr.Read() methods.

这篇关于如何将命名管道字符串从未管理的代码空间发送到托管代码空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆