c#命名管道双向通信

Posted

技术标签:

【中文标题】c#命名管道双向通信【英文标题】:c# named pipe two way communcation 【发布时间】:2016-02-20 13:05:41 【问题描述】:

我有两个用 c++ 和 c# 编写的程序。我想在它们之间使用命名管道建立双向通信。 C#客户端程序可以连接到C++服务器程序创建的命名管道,但是两端都没有收到。

这里是c++部分(服务器):

#include <iostream>
#include <windows.h>
#include <stdlib.h>
#define UNICODE
using namespace std;
HANDLE hnamedPipe = INVALID_HANDLE_VALUE;
BOOL Finished =false;
HANDLE hThread = NULL;
unsigned long __stdcall CS_RcvThr(void * pParam) ;
int main(int argc, char **argv)

    hnamedPipe = CreateNamedPipe(
        "\\\\.\\pipe\\vikeyP",
        PIPE_ACCESS_DUPLEX,
        PIPE_TYPE_MESSAGE|
        PIPE_READMODE_MESSAGE|
        PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        1024,
        1024,
        NMPWAIT_USE_DEFAULT_WAIT,
        NULL);

    if(hnamedPipe == INVALID_HANDLE_VALUE)
    
        cout << "Failed" << endl;
    

    while (true)
    
        cout<< "Waiting for client"<< endl;
        if(!ConnectNamedPipe(hnamedPipe,NULL))
        
            if(ERROR_PIPE_CONNECTED != GetLastError())
            
                cout << "FAIL"<< endl;
            
        
        else
        
            cout<<"Connected!"<<endl;
            hThread = CreateThread( NULL, 0, &CS_RcvThr, NULL, 0, NULL);
            if(hThread) cout<<"read thread created"<<endl; else cout<<"cant crat rd thed\n";
            break;
        
    

    while(1)
    
        cout<<"lst loop"<<endl;
        //Send over the message
        char chResponse[] = "hello\n";
        DWORD cbResponse,cbWritten;
        cbResponse = sizeof(chResponse);

        if (!WriteFile(
        hnamedPipe,
        chResponse,
        cbResponse,
        &cbWritten,
        NULL))
        
            wprintf(L"failiure w/err 0x%08lx\n",GetLastError);
        
        cout<<"Sent bytes :)" << endl;
        Sleep(10);
    


unsigned long __stdcall CS_RcvThr(void * pParam) 
    BOOL fSuccess; 
    char chBuf[100];
    DWORD dwBytesToWrite = (DWORD)strlen(chBuf);
    DWORD cbRead;
    int i;

    while (1)
    
        fSuccess =ReadFile( hnamedPipe,chBuf,dwBytesToWrite,&cbRead, NULL); 
        if (fSuccess)
        
            printf("C++ App: Received %d Bytes : ",cbRead);
            for(i=0;i<cbRead;i++)
                printf("%c",chBuf[i]);
            printf("\n");
        
        if (! fSuccess && GetLastError() != ERROR_MORE_DATA) 
        
            printf("Can't Read\n");
            if(Finished)
                break;
        
    

这里是 C# 部分(客户端):

    private Thread vikeyClientThread;
    public void ThreadStartClient()
    
        Console.WriteLine("Thread client started ID =0 name = 1 " ,
        Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.Name);
        using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "vikeyP"))
        
            // The connect function will indefinately wait for the pipe to become available
            // If that is not acceptable specify a maximum waiting time (in ms)
            Console.WriteLine("Connecting to ViKEY server...");
            pipeStream.Connect();
            Console.WriteLine("Connected :)");

            //Write from client to server
            StreamWriter sw = new StreamWriter(pipeStream);
            while (true)
            
                //Read server reply
                StreamReader sr = new StreamReader(pipeStream);
                string temp = "";
                sw.WriteLine(System.DateTime.Now);
                byte[] c = new byte[200];
                temp = sr.ReadLine();  
                pipeStream.Read(c, 0, c.Length);
                Console.WriteLine("RX =:0", Encoding.UTF8.GetString(c, 0, c.Length));
                Thread.Sleep(500);
            
        
        Console.WriteLine("Vikey pipe Closed");
        Console.WriteLine("Thread with ID =0 name = 1 is closed.",
        Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.Name);
    

【问题讨论】:

发生了什么?错误在哪里?你期望会发生什么,反而会发生什么?发生了哪些控制台输出? @misha130 在 C# 控制台中它应该打印“hello”,在 C++ 控制台中它应该发送当前日期和时间。 你试过'c++ to c++'还是'c# to c#'?可能,使用不同的语言不是问题... @dieter 跨语言使用管道没有问题。我已经完成了,没有问题。 【参考方案1】:

您已将服务器端设置为消息类型与字节类型。如果要读取任意数量的字节,则需要使用名为管道的字节类型。

您将流包装在 2 个对象中,一个 StreamReader 和一个 StreamWriter。不要那样做,只需使用 Stream。您正在尝试逐行阅读,也不要这样做。而是发送要读取的字节数,后跟字节。在客户端,您将读取字节数,然后创建一个足够大的缓冲区然后读取。如果它是文本数据,那么您将使用编码器(可能是 ASCII)将其转换回 C# 字符串。

您的 while(true) 应该检测服务器何时关闭管道。

您可能应该考虑使用异步命名管道。

【讨论】:

以上是关于c#命名管道双向通信的主要内容,如果未能解决你的问题,请参考以下文章

命名管道(C#)

C# 和 Python 之间的命名管道

c# c++通信--命名管道通信

双向命名管道问题

如何使用命名管道通信 C 和 C# 程序

C# 进程通信-命名管道