c#命名管道双向通信

标签 c# c++ ipc named-pipes

我有两个用 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);
    }

最佳答案

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

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

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

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

关于c#命名管道双向通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35523662/

相关文章:

authentication - 一个进程如何与同一主机上的另一个进程安全地进行身份验证和通信

c - 使用 TCP 与 Fortran 进行进程间通信 (IPC)

c# - 单引号 (') and double quote (") ASP.NET 中的奇怪行为

c# - 使用后台工作程序执行 sql 命令时的进度条

c# - Matrix Row - QuickSort递归问题

c++ - libconfig 未定义对 libconfig::Config::Config() 的引用

c++ - 调用基类构造函数的规则是什么?

c++ - 为什么使用类的引用或唯一指针成员是一件坏事?

c# - dllexport 结构指针并返回 uint8_t

linux - 操作系统内核是否以与 IPC 相同的方式与进程通信?