使用命名管道的双向C++到 C# 通信

本文关键字:C++ 通信 管道 | 更新日期: 2023-09-27 18:35:25

我正在尝试在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();
        }
    }
}

使用命名管道的双向C++到 C# 通信

释放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++服务器(在线程中运行):

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 参数。 这使服务器等待客户端连接。