csharp 和 c++ 之间的命名管道

Posted

技术标签:

【中文标题】csharp 和 c++ 之间的命名管道【英文标题】:named pipe between csharp and c++ 【发布时间】:2014-07-10 19:41:02 【问题描述】:

我有两个项目:一个在 c++ 上运行,一个在 c-sharp 上运行。出于某种原因,当我尝试使用 c++ 到 C++ 服务器和客户端工作正常时,如果我尝试使用 c=sharp 和 c-sharp 也是如此,当我尝试使用 c++ 使用 C-sharp 时问题就来了。 这是c-sharp中的服务器代码:

using System;
using System.IO;
using System.IO.Pipes;

class PipeServer

    static void Main()
    
        using (NamedPipeServerStream pipeServer =
            new NamedPipeServerStream("\\\\.\\pipe\\mypipe", PipeDirection.Out))
        
            Console.WriteLine("NamedPipeServerStream object created.");

            // Wait for a client to connect
            Console.Write("Waiting for client connection...");
            pipeServer.WaitForConnection();

            Console.WriteLine("Client connected.");
            try
            
                // Read user input and send that to the client process. 
                using (StreamWriter sw = new StreamWriter(pipeServer))
                
                    sw.AutoFlush = true;
                    Console.Write("Enter text: ");
                    sw.WriteLine(Console.ReadLine());
                
            
            // Catch the IOException that is raised if the pipe is broken 
            // or disconnected. 
            catch (IOException e)
            
                Console.WriteLine("ERROR: 0", e.Message);
            
        
    

这是c++中的客户端代码:

#include "stdafx.h"
#include <windows.h> 
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUFSIZE 512

int _tmain(int argc, _TCHAR* argv[])

    HANDLE hPipe; 
   LPTSTR lpvMessage=TEXT("MSR"); 
   TCHAR  chBuf[BUFSIZE]; 
   BOOL   fSuccess = FALSE; 
   DWORD  cbRead, cbToWrite, cbWritten, dwMode; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mypipe"); 

   if( argc > 1 )
      lpvMessage = argv[1];

// Try to open a named pipe; wait for it, if necessary. 

   while (1) 
    
      hPipe = CreateFile( 
         lpszPipename,   // pipe name 
         GENERIC_READ |  // read and write access 
         GENERIC_WRITE, 
         0,              // no sharing 
         NULL,           // default security attributes
         OPEN_EXISTING,  // opens existing pipe 
         0,              // default attributes 
         NULL);          // no template file 

   // Break if the pipe handle is valid. 

      if (hPipe != INVALID_HANDLE_VALUE) 
         break; 

      // Exit if an error other than ERROR_PIPE_BUSY occurs. 

      if (GetLastError() != ERROR_PIPE_BUSY) 
      
         _tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() ); 
         return -1;
      

      // All pipe instances are busy, so wait for 20 seconds. 

      if ( ! WaitNamedPipe(lpszPipename, 20000)) 
       
         printf("Could not open pipe: 20 second wait timed out."); 
         return -1;
       
    

// The pipe connected; change to message-read mode. 

   dwMode = PIPE_READMODE_MESSAGE; 
   fSuccess = SetNamedPipeHandleState( 
      hPipe,    // pipe handle 
      &dwMode,  // new pipe mode 
      NULL,     // don't set maximum bytes 
      NULL);    // don't set maximum time 
   if ( ! fSuccess) 
   
      _tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); 
      return -1;
   

// Send a message to the pipe server. 

   cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);
   _tprintf( TEXT("Sending %d byte message: \"%s\"\n"), cbToWrite, lpvMessage); 

   fSuccess = WriteFile( 
      hPipe,                  // pipe handle 
      lpvMessage,             // message 
      cbToWrite,              // message length 
      &cbWritten,             // bytes written 
      NULL);                  // not overlapped 

   if ( ! fSuccess) 
   
      _tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); 
      return -1;
   

   printf("\nMessage sent to server, receiving reply as follows:\n");

   do 
    
   // Read from the pipe. 

      fSuccess = ReadFile( 
         hPipe,    // pipe handle 
         chBuf,    // buffer to receive reply 
         BUFSIZE*sizeof(TCHAR),  // size of buffer 
         &cbRead,  // number of bytes read 
         NULL);    // not overlapped 

      if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
         break; 

      _tprintf( TEXT("\"%s\"\n"), chBuf ); 
    while ( ! fSuccess);  // repeat loop if ERROR_MORE_DATA 

   if ( ! fSuccess)
   
      _tprintf( TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError() );
      return -1;
   

   //printf("\n<End of message, press ENTER to terminate connection and exit>");
   //_getch();

   CloseHandle(hPipe); 
    return 0;

当客户端尝试连接到服务器时,它返回错误代码 2,这意味着文件不存在。

【问题讨论】:

我不确定 Windows 管道,但管道通常是单向的。因此,在应用程序中,您以写入模式打开一个管道,而在另一个应用程序中,您以读写模式打开它。如果管道的打开成功,您将遇到另一个问题:当另一端没有人从管道读取时写入管道。 @JoachimPileborg 微软网站说 NamedPipes 可以是单向或双工!!!请看下面link 【参考方案1】:

我遇到了同样的问题,但是服务器是读取器,客户端是写入器。我刚刚将 c# 中的 pipename 更改为“mypipe”,并且它起作用了。

【讨论】:

以上是关于csharp 和 c++ 之间的命名管道的主要内容,如果未能解决你的问题,请参考以下文章

c#命名管道双向通信

如何在 Mac OS 上用 C++ 实现命名管道?

使用命名管道的两种 C++ 到 C# 通信

命名管道 C# 服务器 C++ .dll 客户端不工作?

C++ 中的序列化和 C# 中的反序列化,对于命名管道,反之亦然

在断开连接之前等待读取命名管道