如何使用命名管道从 C++ 调用 WCF 方法?

Posted

技术标签:

【中文标题】如何使用命名管道从 C++ 调用 WCF 方法?【英文标题】:How do I call a WCF method from c++ using Named pipes? 【发布时间】:2012-07-30 19:27:55 【问题描述】:

更新: 查看协议here,我无法弄清楚Unsized Envelope Record 中的内容。我在网上找不到任何示例。

原文:

我有以下 WCF 服务

    static void Main(string[] args)
    
        var inst = new PlusFiver();
        using (ServiceHost host = new ServiceHost(inst,
            new Uri[]  new Uri("net.pipe://localhost") ))
        
            host.AddServiceEndpoint(typeof(IPlusFive), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "PipePlusFive");
            host.Open();
            Console.WriteLine("Service is Available. Press enter to exit.");
            Console.ReadLine();
            host.Close();
        
    

   [ServiceContract]
   public interface IPlusFive
   
       [OperationContract]
       int PlusFive(int value);
   


   [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
   public class PlusFiver : IPlusFive
   
      public int PlusFive(int value)
      
          Console.WriteLine("Adding 5 to " + value);
          return value + 5;
            
   

我输出了添加的 5 行,所以我知道服务器是否处理了 请求与否。

我有一个用于测试的 .NET 客户端,一切正常 预计。

现在我想为此创建一个非托管 C++ 客户端。

我想出了如何获取管道的名称并写入它。 我已经从here下载了协议

我可以写到管道,但我不能读到它。每当我尝试从中读取时,我都会收到 ERROR_BROKEN_PIPE 109 (0x6D) The pipe has been ended. 错误。如果我将读取替换为写入,则写入成功,因此我认为管道不会关闭,至少在我尝试读取之前不会。

这是我连接到管道的方式。

HANDLE OpenPipe(OLECHAR* bstrGuid)

    wstring pipeName = L"\\\\.\\pipe\\";
    wstring strGuid = bstrGuid;
    pipeName.append(strGuid.substr(1,36));
    wcout << "Pipe Name " << endl;
    wcout << pipeName.c_str() << endl;

    HANDLE hPipe = CreateFile(pipeName.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
    if(hPipe == INVALID_HANDLE_VALUE)
    
        wcout << "failed to create pipe" << endl;
        system("pause");
        return NULL;
    
    return hPipe;

这就是我创建要发送的第一条消息的方式

std::list<wchar_t> GetFirstMessage()

    std::list<wchar_t> message;
    message.push_back(0x00);// version record
    message.push_back(0x01);// major version
    message.push_back(0x00);// minor version
    message.push_back(0x01);// mode record
    message.push_back(0x01);// singleton-unsized mode
    message.push_back(0x02);// via record

    wstring url = L"net.pipe://localhost/PipePlusFive";
    message.push_back(url.length());// via length
    for(int x= 0;x<url.length();x++)
    
        message.push_back(url[x]); // via
    
    message.push_back(0x03);
    message.push_back(0x08);
    return message;

这就是我将它写入文件的方式。

int WriteMessage(HANDLE hPipe, LPVOID message, int size)

    DWORD bytesWritten;

    BOOL bWrite = WriteFile(hPipe, &message, size, &bytesWritten, NULL);
    wcout << "Bytes Written: " << bytesWritten << endl;
    if(bWrite == false)
    
        wcout << "fail"<<endl;
        CloseHandle(hPipe);
        system("pause");
        return 1;
    
    return 0;


    list<wchar_t> full_message = GetFirstMessage();
int result = WriteMessage(hPipe, &full_message, full_message.size());   
if (result == 1)
 return 1;

这是我写结束信息的方式

    wchar_t message = 12;
result = WriteMessage(hPipe, &message, 1);
if (result == 1)
 return 1;

这是我尝试阅读响应的方式

    char buffer[10];
DWORD bytesRead;
BOOL bRead = ReadFile(hPipe, buffer, 1, &bytesRead, NULL);
if(bRead == false)

    wcout << "fail read"<<endl;
    wcout << "error: " << GetLastError() << endl;
    CloseHandle(hPipe);
    system("pause");
    return 1;

我是 C++ 新手,所以我不知道我是否没有正确遵循协议或在尝试这样做时犯了一个愚蠢的错误?

更新: 问题是我将指针地址写入命名管道而不是列表的内容。我已经解决了这个问题,我现在可以阅读序言确认记录。现在我必须弄清楚协议的下一部分需要发送什么。

【问题讨论】:

您不能使用托管 C++ 或其他更简单的 WCF 绑定(REST 等)吗? 我不能使用托管 C++。我认为 REST 会很慢。 这里有一个解决方案:***.com/questions/686452/… 但它使用了一些托管 C++ 使用了基本的 http 绑定。我需要使用 NetNamedPipeBinding MSFT 建议使用 Windows Web 服务 - msdn.microsoft.com/en-us/… 或者,您可以使您的 WCF 接口 COMVisible 并从中创建一个 tlb developerfusion.com/article/2134/… 【参考方案1】:

检查这是否适合你

    尝试打开命名管道。 (创建文件) 设置指定命名管道的读取模式和阻塞模式。 (SetNamedPipeHandleState) 向管道服务器发送消息并接收其响应。 (写文件,读文件) 关闭管道。 (关闭句柄)

【讨论】:

以上是关于如何使用命名管道从 C++ 调用 WCF 方法?的主要内容,如果未能解决你的问题,请参考以下文章

带有命名管道的 WCF:如何允许并行调用?

如何从 C++ 代码引发事件并在另一个进程的 C# 代码中调用处理程序?

如何在 WCF 中自动重新连接命名管道绑定

C# 进程通信-命名管道

c++ 如何在构造函数中启动一个线程,从命名管道读取数据?

保护 WCF 使用的命名管道