如何使用命名管道(C ++服务器,C#客户端)

时间:2012-03-12 23:38:28

标签: c# c++ windows ipc named-pipes

我正在尝试开始使用命名管道,因为我将来需要将它们用于我的项目。

目前我有一个C ++服务器,它等待客户端连接并通过测试消息发送。我粗略地跟着这个tutorial开始了。相关代码如下:

    #define MESSAGE L"TestMessage"

HANDLE hnamedPipe = INVALID_HANDLE_VALUE;

hnamedPipe = CreateNamedPipe(
    L"\\\\.\\pipe\\testpipe",
    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;
        }
    }

    cout<<"Connected!"<<endl;

    //Send over the message
    wchar_t chResponse[] = MESSAGE;
    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;
}

客户端代码(C#)如下:

        using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut))
        {
            while (true)
            {
                Console.WriteLine("Connecting to server...");
                pipeClient.Connect();

                Console.WriteLine("Connected :)");
                Console.WriteLine(pipeClient.ReadByte());
                pipeClient.Close();
                Console.WriteLine("Closed");
            }

        }

目前我已经让客户端成功连接到服务器并打印出第一个字节。我想知道如何做两件事:

  1. 阅读整个消息 - 我尝试在pipeClient上使用StreamReader来读取消息,但它无限期地挂在ReadLine()上。

  2. 持续发送消息 - 我希望服务器在消息发送到客户端后发送消息,客户端将一次读取消息并将其打印出来。我对IPC有点无能为力,所以一开始我尝试让客户端断开连接并在while(true)循环中重新连接到服务器,而服务器处于一个真正的循环中,在顶部总是等待新的客户端连接之前发送另一条消息。我的尝试是在上面的代码中。

  3. 对此的任何帮助将不胜感激。最终目标是将图像从服务器发送到客户端。然后客户端将它们实时打印到屏幕上。在尝试使用图像数据之前,我希望能够使用简单的字符串消息。

    编辑:

    最终我希望能够从客户端向服务器发送消息,表明它想要获取最新的图像帧,然后服务器将发送最新的帧,然后客户端将在屏幕上显示。所以流程是:

    1. 客户 - &gt;服务器:客户端需要最新帧信息的指示符。 (简单的东西,可能是值为1的unsigned int)
    2. 服务器 - &gt;客户:最新的框架信息。 (640x480图像存储在具有RGB字节值的字节数组中)
    3. 客户端:在显示屏上显示框架。

1 个答案:

答案 0 :(得分:4)

ReadLine挂起,因为它正在等待换行符,而测试消息不包含换行符。

如果您希望服务器连续发送消息,只需在WriteFile呼叫周围循环。您不需要连接多次。同样在客户端中,将循环放在ReadLine

如果每条消息都包含由换行符终止的文本,那么这应该足够了,但如果您真的希望管道客户端在消息模式下工作,则需要调用:

pipeClient.ReadMode = PipeTransmissionMode.Message;

但是,我怀疑这会与StreamReader很好地互动。相反,您应该使用pipeClient.Read阅读单个邮件。

<强>更新

回答你的新问题:

在服务器上,一旦客户端连接进入一个循环,其中:

  • 服务器从客户端读取。这将阻止,直到客户端请求一个框架。
  • 服务器发送一个框架。

在客户端上,一旦连接到服务器,输入一个循环:

  • 客户端发送“请发送框架”消息。
  • 客户端从服务器读取以获取帧。
  • 客户端显示框架。

我不会使用消息模式管道。如果帧的大小是固定的,则客户端知道从服务器读取多少数据。否则,在帧的前面加上一个包含其长度的uint。