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

提问

我试图开始使用命名管道,因为将来我需要将其用于我的项目.

目前,我有一个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");
            }

        }

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

>阅读整个消息-我尝试在pipeClient上使用StreamReader读取消息,但它无限期地挂在ReadLine()上.
>连续发送消息-我希望服务器将消息后的消息发送给客户端,客户端将一次读取它们并打印出来.我对IPC一点儿也不了解,所以起初我尝试使客户端断开连接,并在while(true)循环中重新连接到服务器,而服务器处于while true循环中,该循环总是在顶部等待新的客户端连接之前发送另一条消息.我的尝试是在上面的代码中.

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

编辑:

最终,我希望能够从客户端向服务器发送一条消息,指示它想要获取最新的图像帧,然后服务器将通过客户端随后在屏幕上显示的最新帧进行发送.因此流程为:

>客户->服务器:指示客户端需要最新的帧信息. (有些简单的事情,可能是值为1的无符号整数)
>服务器->客户:最新的框架信息. (640×480图像以RGB字节值存储在字节数组中)
>客户端:在显示屏上显示框架.

最佳答案

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

如果要服务器连续发送消息,只需在WriteFile调用周围放一个循环即可.您不需要连接多次.同样,在客户端中,将循环放在ReadLine周围.

如果每个消息都包含以换行符结尾的文本,则该内容就足够了,但是如果您确实希望管道客户端以消息模式工作,则需要调用:

pipeClient.ReadMode = PipeTransmissionMode.Message;

但是,我怀疑这是否可以与StreamReader很好地交互.相反,您应该使用pipeClient.Read阅读单个消息.

更新资料

要回答您的新问题:

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

>服务器从客户端读取数据.这将阻塞,直到客户端请求一个帧为止.
>服务器发送一个帧.

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

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

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

评论