2012-08-01 16 views
10

ACTUALIZACIÓN: Mirando a través del protocolo here, no puedo entender lo que entra en el registro de envolvente sin clasificar. No puedo encontrar ningún ejemplo en línea.¿Cómo puedo llamar a un método WCF desde C++ utilizando canalizaciones con nombre?

ORIGINAL:

tengo el siguiente servicio 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; 
     }  
    } 

salida que la línea de la adición de 5, así que sé si el servidor procesa la solicitud o no.

Tengo un cliente .NET que utilicé para probar esto y todo funciona como esperado.

Ahora quiero hacer un cliente C++ no administrado para esto.

Descubrí cómo obtener el nombre de la tubería y escribir en ella.
He descargado el protocolo de here

Puedo escribir en el tubo, pero no puedo leerlo. Cada vez que intento leer de él obtengo un error de ERROR_BROKEN_PIPE 109 (0x6D) The pipe has been ended.. Si reemplazo la lectura con una escritura, la escritura es exitosa, así que no creo que la tubería esté cerrada, al menos no hasta que intente hacer una lectura.

Así es como me estoy conectando a la tubería.

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

así es como estoy creando el primer mensaje que estoy enviando

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

Ésta es la forma en que estoy escribiendo en el archivo.

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

Así es como estoy escribiendo el mensaje final

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

aquí es cómo estoy tratando de leer la respuesta

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

Soy nuevo en C++, por lo No sé si no estoy siguiendo el protocolo correctamente o cometiendo un error estúpido en la forma en que intento hacer esto.

ACTUALIZACIÓN: El problema era que estaba escribiendo la dirección del puntero a la tubería con nombre en lugar de los contenidos de la lista. Lo arreglé Y ahora puedo leer el Registro Preliminar de Preámbulo. Ahora tengo que averiguar qué debe enviarse para la próxima parte del protocolo.

+0

¿No puede usar C++ administrado u otro enlace más fácil de WCF (REST, etc.)? –

+0

No puedo usar C++ administrado. Creo que el REST sería lento. – scott

+0

Aquí hay una solución aquí: http://stackoverflow.com/questions/686452/create-wcf-service-for-unmanaged-c-clients pero utiliza algunas piezas de C++ administradas –

Respuesta

0

Comprobar si esto funciona para usted

  1. intenta abrir una conexión con nombre. (CreateFile)
  2. Establezca el modo de lectura y el modo de bloqueo de la tubería con nombre especificada. (SetNamedPipeHandleState)
  3. Envía un mensaje al servidor de pipa y recibe su respuesta. (WriteFile, ReadFile)
  4. Cierre la tubería.(CloseHandle)
Cuestiones relacionadas