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

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

目前,我有一个C ++服务器,等待客户端连接并发送testing消息。 我大致遵循本教程开始。 相关代码如下:

#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"); } } 

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

  1. 阅读完整的消息 – 我试图通过PipeClient使用StreamReader来读取消息,但它无限期地挂在ReadLine()上。

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

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

编辑:

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

  1. 客户端 – >服务器:指示客户端需要最新的帧信息。 (很简单,也许是1的无符号整数)
  2. 服务器 – >客户端:最新的框架信息。 (以RGB字节值存储在字节数组中的640×480图像)
  3. 客户端:在显示器上显示框架。

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

如果您希望服务器不断发送消息,只需在WriteFile调用周围放置一个循环即可。 您不需要连接多次。 同样在客户端,围绕ReadLine放置循环。

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

 pipeClient.ReadMode = PipeTransmissionMode.Message; 

不过,我怀疑这会与StreamReader交互。 相反,您应该使用pipeClient.Read读取单个消息。

更新

要回答你的新问题:

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

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

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

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

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