2012-08-01 14 views
10

CẬP NHẬT: Nhìn qua giao thức here, tôi không thể tìm ra những gì đi vào Bản ghi Phong bì Chưa được phân loại. Tôi không thể tìm thấy bất kỳ ví dụ trực tuyến nào.Làm cách nào để gọi một phương thức WCF từ C++ bằng cách sử dụng các đường ống có tên?

ORIGINAL:

tôi có các dịch vụ WCF sau

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

tôi sản lượng thêm 5 dòng vì vậy tôi biết nếu máy chủ xử lý yêu cầu hay không.

Tôi có ứng dụng .NET mà tôi đã sử dụng để kiểm tra điều này và mọi thứ hoạt động như được mong đợi.

Bây giờ tôi muốn tạo một trình khách C++ không được quản lý cho việc này.

Tôi đã tìm ra cách lấy tên của đường ống và ghi vào đó.
Tôi đã tải xuống giao thức từ here

Tôi có thể viết thư cho đường ống nhưng tôi không thể đọc được. Bất cứ khi nào tôi cố gắng đọc từ nó, tôi nhận được một lỗi ERROR_BROKEN_PIPE 109 (0x6D) The pipe has been ended.. Nếu tôi thay thế đọc bằng ghi, viết là thành công, vì vậy tôi không nghĩ rằng ống được đóng lại, ít nhất là không cho đến khi tôi cố gắng đọc.

Đây là cách tôi kết nối với đường ống.

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

đây là cách tôi đang tạo ra thông điệp đầu tiên mà tôi gửi

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

Đây là cách tôi đang viết nó vào tập tin.

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

Dưới đây là cách tôi đang viết thông điệp cuối

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

ở đây là làm thế nào tôi đang cố gắng để đọc những phản ứng

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

Tôi mới để C++, vì vậy Tôi không biết nếu tôi không tuân theo giao thức một cách chính xác hoặc làm cho một sai lầm ngu ngốc trong cách tôi đang cố gắng để làm điều này?

CẬP NHẬT: Vấn đề là tôi đã viết địa chỉ con trỏ vào đường ống được đặt tên thay vì nội dung của danh sách. Tôi đã khắc phục điều đó Và bây giờ tôi có thể đọc Bản ghi Ack Lời nói đầu. Bây giờ tôi phải tìm ra những gì cần phải được gửi cho phần tiếp theo của giao thức.

+0

Bạn không thể sử dụng C++ được quản lý hoặc liên kết WCF dễ dàng hơn (REST, v.v ...)? –

+0

Tôi không thể sử dụng managed C++. Tôi nghĩ REST sẽ chậm lại. – scott

+0

Đây là một giải pháp ở đây: http://stackoverflow.com/questions/686452/create-wcf-service-for-unmanaged-c-clients nhưng nó sử dụng một số phần quản lý C++ –

Trả lời

0

Kiểm tra nếu điều này làm việc cho bạn

  1. Cố gắng mở một đường ống đặt tên. (CreateFile)
  2. Đặt chế độ đọc và chế độ chặn của ống được chỉ định. (SetNamedPipeHandleState)
  3. Gửi tin nhắn đến máy chủ đường ống và nhận phản hồi của nó. (WriteFile, ReadFile)
  4. Đóng ống.(CloseHandle)