2012-03-12 186 views
3

我想开始使用命名管道工作,我将需要使用它们在未来我的一个项目。如何使用命名管道(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"); 
      } 

     } 

在我已经得到了客户端成功连接到服务器的时刻,它打印出的第一个字节。我想知道如何做两件事情:

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

  2. 连续发送了邮件 - 我希望服务器消息后发送消息给客户端,这将在一次一个阅读并打印出来。我有点无能IPC所以刚开始我试图让客户端断开并重新连接在一段时间(true)循环的服务器,而服务器在一段时间真正的循环在顶部总是等待前一个新的客户端连接发送另一条消息。我试图在上面的代码中。

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

编辑:

最后,我希望能够从客户端发送信息到服务器,表明它想获得最新的图像帧时,服务器将发送了最新的帧的客户端将其再在屏幕上显示。所以流程如下:

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

对于你的第一个问题,使用类似'StreamReader'(只有当你的消息是文本时才使用它)。 'StreamReader.ReadToEnd'将从流中读取所有可用的数据。 – 2012-03-13 00:12:02

+0

嗨,我试过了,但它一直等到C++服务器关闭之前才打印出所有消息。最终,我希望能够从客户端向服务器发送一条消息,表明它想要获取最新的图像帧,然后服务器将发送最新的帧,然后客户端将在屏幕上显示该帧。 – Jkh2 2012-03-13 15:26:43

回答

4

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

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

如果每个消息由一个换行符终止,则应该足够了文本,但如果你真的想管客户端短信模式下工作,你需要调用:

pipeClient.ReadMode = PipeTransmissionMode.Message; 

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

更新

要回答新问题:

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

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

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

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

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

+0

@ Jkh2:我已经更新了我的答案。 – arx 2012-03-13 16:39:44

+0

谢谢,我已经将这个逻辑加入到我的代码中,它工作的很棒:) – Jkh2 2012-03-13 16:53:10

相关问题