Estoy tratando de escribir en una canalización con nombre y leer lo mismo. Considere el siguiente fragmento de código (el manejo de errores se elimina por brevedad):
const char * pipeName = "\\\\.\\pipe\\pipe"; const char * buffWrite = "SOME TEXT"; unsigned buffLength = strlen(buffWrite); char buffRead[1024]; DWORD nWritten, nRead; HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, 0); HANDLE hFile = CreateFile(pipeName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); WriteFile(hFile, buffWrite, buffLength, &nWritten, 0); CloseHandle(hFile); //the next line fails with >>All pipe instances are busy.<< hFile = CreateFile(pipeName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); ReadFile(hFile, buffRead, buffLength, &nRead, 0); ...Sin embargo, cuando intento reabrir la tubería para leer, la llamada CreateFile falla con "Todas las tuberías están ocupadas".
¿Que me estoy perdiendo aqui?
EDITAR. Mirar a escondidas funciona bien, es decir
DWORD nRead, nTotal, nLeft; PeekNamedPipe(hPipe, buffRead, buffLength, &nRead, &nTotal, &nLeft);devuelve los datos escritos correctamente.
OBSERVACIÓN. Esta es una prueba de concepto para algo más grande. No habrá nuevos subprocesos ni procesos involucrados.
La razón por la que obtiene ese código de error específico es que solo creó una instancia de la canalización con nombre y ya la usó. (Puede crear una nueva instancia llamando a CreateNamedPipe por segunda vez, o puede reutilizar una instancia existente llamando a DisconnectNamedPipe ).
Sin embargo, según su comentario, creo que desea que la llamada a ReadFile recupere los datos escritos por la llamada a WriteFile, es decir, desea la misma instancia de la canalización, no una nueva.
Para hacer eso, no abra un nuevo mango. Utilice el identificador existente, hPipe .
(Tenga en cuenta que cada instancia de tubería tiene dos extremos: un extremo del servidor y un extremo del cliente. El identificador de CreateNamedPipe siempre está en el extremo del servidor, y el identificador de CreateFile siempre está en el extremo del cliente. Los datos escritos en el extremo del servidor solo pueden ser leer desde el extremo del cliente, y viceversa.)
Está tratando de usar una tubería con nombre como una especie de búfer: el cliente se conecta a él, coloca algunos datos, luego se desconecta, luego otro cliente se conecta y recupera estos datos. Este es un enfoque no válido, la tubería con nombre es solo eso: una tubería , tiene dos lados: el lado del servidor y el lado del cliente , el servidor y el cliente podrían comunicarse a través de él. Escenario habitual de uso de tuberías:
CreateNamedPipe ;ConnectNamedPipe ;CreateFile ;ReadFile/WriteFile ;DisconnectNamedPipe y podría reactivarse nuevamente con ConnectNamedPipe .Puede ver un ejemplo completo en MSDN aquí .
Es porque ya se han abierto ambos extremos del tubo (*)...
Primero se abrió con la llamada CreatePipe, el otro fue con la primera llamada CreateFile. No debe intentar abrir una vez más la tubería, simplemente lea del MANGO hPipe:
const char * pipeName = "\\\\.\\pipe\\pipe"; const char * buffWrite = "SOME TEXT"; unsigned buffLength = strlen(buffWrite); char buffRead[1024]; DWORD nWritten, nRead; HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, 0); HANDLE hFile = CreateFile(pipeName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); WriteFile(hFile, buffWrite, buffLength, &nWritten, 0); CloseHandle(hFile); ReadFile(hPipe, buffRead, buffLength, &nRead, 0); // nRead=9, buffRead="SOME TEXT" ... (*) Sí especificó PIPE_UNLIMITED_INSTANCES para el parámetro nMaxInstances en la llamada CreateNamedPipe , pero como nunca llamó a ConnectNamedPipe para crear otros puntos finales, solo se permitió un CreateFile .