How do I call a WCF method from c++ using Named pipes?

允我心安 提交于 2019-12-04 18:28:22

问题


UPDATE: Looking through the protocol here, I can't figure out what goes into the Unsized Envelope Record. I can't find any examples online.

ORIGINAL:

I have the following WCF service

    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;
      }      
   }

I output the adding 5 line so I know if the server processed the request or not.

I have a .NET client that I used to test this and everything works as expected.

Now I want to make an unmanaged C++ client for this.

I figured out how to get the name of the pipe, and write to it.
I've downloaded the protocol from here

I can write to the pipe but I can't read to it. Whenever I try to read from it I get a ERROR_BROKEN_PIPE 109 (0x6D) The pipe has been ended. error. If I replace the read with a write, the write is successful, so I don't think that the pipe is closed, at least not until I try to do a read.

Here is how I'm connecting to the pipe.

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;
}

this is how i'm creating the first message that I'm sending

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;
}

This is how I'm writing it to the file.

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;}

Here is how I'm writing the end message

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

here is how I'm trying to read the response

    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;
}

I'm new to c++, so I don't know if I'm not following the protocol correctly or making a stupid mistake in the way I'm trying to do this?

UPDATE: The problem was that I was writing the pointer address to the named pipe instead of the contents of the list. I've fixed that And I'm now able to read the Preamble Ack Record. Now I have to figure out what needs to be sent for the next part of the protocol.


回答1:


Check if this works for you

  1. Try to open a named pipe. (CreateFile)
  2. Set the read mode and the blocking mode of the specified named pipe. (SetNamedPipeHandleState)
  3. Send a message to the pipe server and receive its response. (WriteFile, ReadFile)
  4. Close the pipe. (CloseHandle)


来源:https://stackoverflow.com/questions/11767072/how-do-i-call-a-wcf-method-from-c-using-named-pipes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!