使用命名管道的两种 C++ 到 C# 通信

Posted

技术标签:

【中文标题】使用命名管道的两种 C++ 到 C# 通信【英文标题】:Two way C++ to C# communication using named pipes 【发布时间】:2012-05-24 15:22:24 【问题描述】:

我正在尝试在 VC++ 6 应用程序和 C# 应用程序之间进行双向通信。我正在使用命名管道。在我的 C++ 代码中,我可以从 C# 客户端读取消息,但随后服务器“死机”,我必须再次重新启动它。

我想做的是让 C# 应用程序连接到 C++ 应用程序,请求状态,然后 C++ 应用程序关闭并检查状态,然后返回“忙碌”或“空闲”。

我无法将任何内容写回 C# 客户端,因为它说连接已关闭。我注释掉的一些东西是我已经尝试过的。

C++ 代码(作为线程启动)

UINT CNamedPipe::StartNamedPipeServer()

LPTSTR lpszPipename = "\\\\.\\pipe\\SAPipe"; 
    HANDLE hPipe; 
    BOOL flg;
    DWORD dwWrite,dwRead;
    char szServerUpdate[200];
    char szClientUpdate[200];

    hPipe = CreateNamedPipe (    lpszPipename, 
                                PIPE_ACCESS_DUPLEX,
                                PIPE_TYPE_MESSAGE | 
                                PIPE_READMODE_MESSAGE | 
                                PIPE_NOWAIT,                    //changed from nowait
                                PIPE_UNLIMITED_INSTANCES,    // max. instances 
                                BUFSIZE,                    // output buffer size 
                                BUFSIZE,                    // input buffer size 
                                PIPE_TIMEOUT,                // client time-out 
                                NULL);                        // no security attribute 

    if (hPipe == INVALID_HANDLE_VALUE) 
        return 0;

    ConnectNamedPipe(hPipe, NULL);

    while(m_bServerActive)  //This seems to work well ....
    

        //Read from client
        flg = ReadFile(hPipe,szClientUpdate,strlen(szClientUpdate),&dwRead, NULL);

        if(flg) //Read something from the client!!!!
        
            CString csMsg,csTmp;

            for(int i=0;i<dwRead;i++)
                csTmp.Format("%c",szClientUpdate[i]);
                csMsg += csTmp;
            


            AfxMessageBox("Client message: " + csMsg);

            strcpy( szServerUpdate,"busy");

            //Write status to Client
            flg = WriteFile(hPipe, szServerUpdate, strlen(szServerUpdate), &dwWrite, NULL);

            EndServer();
            StartServer();
        

    

    return 0;

C#代码:

public void ThreadStartClient(object obj)
    
        // Ensure that we only start the client after the server has created the pipe
        ManualResetEvent SyncClientServer = (ManualResetEvent)obj;

        // Only continue after the server was created -- otherwise we just fail badly
        // SyncClientServer.WaitOne();

        using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "SAPipe"))
        
            // The connect function will indefinately wait for the pipe to become available
            // If that is not acceptable specify a maximum waiting time (in ms)
            pipeStream.Connect();

            //Write from client to server
           using (StreamWriter sw = new StreamWriter(pipeStream))
            
                sw.WriteLine("What's your status?");
           

            //Read server reply
            /*using (StreamReader sr = new StreamReader(pipeStream))
            
                string temp = "";
                temp = sr.ReadLine();   //Pipe is already closed here ... why?

                MessageBox.Show(temp);

            */

            //pipeStream.Close();

        
    

【问题讨论】:

【参考方案1】:

处理StreamWriterStreamReader 将关闭底层流。

因此,您的 using 语句将导致流关闭。

    public void ThreadStartClient(object obj)
    
            // Ensure that we only start the client after the server has created the pipe
            ManualResetEvent SyncClientServer = (ManualResetEvent)obj;

            // Only continue after the server was created -- otherwise we just fail badly
            // SyncClientServer.WaitOne();

            using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "SAPipe"))
            
                // The connect function will indefinately wait for the pipe to become available
                // If that is not acceptable specify a maximum waiting time (in ms)
                pipeStream.Connect();


                //Write from client to server
                StreamWriter sw = new StreamWriter(pipeStream))
                sw.WriteLine("What's your status?");

                //Read server reply
                StreamReader sr = new StreamReader(pipeStream)
                string temp = "";
                temp = sr.ReadLine();   //Pipe is already closed here ... why?

                MessageBox.Show(temp);
            
    

还应注意,由于您将流包装在 using 语句中,因此不需要注释掉的 pipeStream.Close() 函数。

【讨论】:

谢谢,帮助很大。我将更改我的代码,看看会发生什么。您可能已经猜到了,我是 C# 新手。 没问题,记得点选票下的勾,这样你的支持率会更高!【参考方案2】:

好的,让它适用于我的应用程序......谢谢 Blam!

这是 C++ 服务器(在线程中运行):

UINT CNamedPipe::StartNamedPipeServer()

    if(!m_bServerActive)
        return 0;

    LPTSTR lpszPipename = "\\\\.\\pipe\\MyPipe"; 
        HANDLE hPipe; 
        BOOL flg;
        DWORD dwWrite,dwRead;
        char szServerUpdate[200];
        char szClientUpdate[200];

        hPipe = CreateNamedPipe (    lpszPipename, 
                                    PIPE_ACCESS_DUPLEX,
                                    PIPE_TYPE_MESSAGE | 
                                    PIPE_READMODE_MESSAGE | 
                                    PIPE_WAIT,                  //HAS TO BE THIS
                                    PIPE_UNLIMITED_INSTANCES,    // max. instances 
                                    BUFSIZE,                    // output buffer size 
                                    BUFSIZE,                    // input buffer size 
                                    PIPE_TIMEOUT,                // client time-out 
                                    NULL);                        // no security attribute 

        if (hPipe == INVALID_HANDLE_VALUE) 
            return 0;

        ConnectNamedPipe(hPipe, NULL);


        strcpy( szServerUpdate,"busy");

        //Write status to Client
        flg = WriteFile(hPipe, szServerUpdate, strlen(szServerUpdate), &dwWrite, NULL);

        EndServer();
        StartServer();

        return 0;

这是 C# 客户端:

public void ThreadStartClient(object obj)
        
            // Ensure that we only start the client after the server has created the pipe
            ManualResetEvent SyncClientServer = (ManualResetEvent)obj;

            using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "MyPipe", PipeDirection.InOut))
            

                // The connect function will indefinately wait for the pipe to become available
                // If that is not acceptable specify a maximum waiting time (in ms)
                pipeStream.Connect();

                if (!pipeStream.IsConnected)    //It thinks it's connected but can't read anything ....
                
                    MessageBox.Show("Failed to connect ....");
                    return;
                

                //Read server reply
                StreamReader sr = new StreamReader(pipeStream);

                char[] c = new char[200];

                while (sr.Peek() >= 0)
                
                    sr.Read(c, 0, c.Length);
                

                string s = new string(c);
                MessageBox.Show(s);
            
        

我实际上并没有从客户端向服务器发送任何内容,因为我不需要...其中的关键是 CreateNamedPipe() 函数中的 PIPE_WAIT 参数。这使服务器等待客户端连接。

【讨论】:

以上是关于使用命名管道的两种 C++ 到 C# 通信的主要内容,如果未能解决你的问题,请参考以下文章

c#命名管道双向通信

C# 服务器和 C++ 客户端之间的命名管道通信

C# 进程通信-命名管道

带有 c# 服务器的命名管道客户端 (c++)

使用命名管道将图像从 C++ 发送到 C# 应用程序

命名管道 C# 服务器 C++ .dll 客户端不工作?