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.
¿No puede usar C++ administrado u otro enlace más fácil de WCF (REST, etc.)? –
No puedo usar C++ administrado. Creo que el REST sería lento. – scott
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 –