2012-08-01 63 views
10

更新: 通過協議here看,我無法弄清楚什麼進入Unsized Envelope Record。我在網上找不到任何例子。如何使用命名管道從C++調用WCF方法?

ORIGINAL:

我有以下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; 
     }  
    } 

I輸出的加法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++,所以我不知道我是不是正確地遵循協議或者以我嘗試這樣做的方式犯了一個愚蠢的錯誤?

更新: 問題是我正在寫指針地址到命名管道而不是列表的內容。我已經解決了這個問題,現在我可以閱讀Preamble Ack Record。現在我必須弄清楚協議的下一部分需要發送什麼。

+0

不能使用託管C++或其他更簡單的WCF綁定(REST等)嗎? – 2012-08-10 14:10:08

+0

我無法使用託管C++。我認爲REST會變慢。 – scott 2012-08-10 14:11:41

+0

這裏是一個解決方案在這裏:http://stackoverflow.com/questions/686452/create-wcf-service-for-unmanaged-c-clients,但它使用了一些託管C++ – 2012-08-10 14:53:13

回答

0

檢查,如果這對你的作品

  1. 嘗試打開一個命名管道。 (CreateFile)
  2. 設置指定命名管道的讀取模式和阻塞模式。 (SetNamedPipeHandleState)
  3. 發送消息到管道服務器並接收其響應。 (WriteFile,ReadFile)
  4. 關閉管道。(CloseHandle)