Tengo un servidor y un cliente de pipa nombrados. (Haciendo esto en VC++).Problema al volver a conectar a la tubería con nombre
servidor hace
- CreateNamedPipe
- ConnectNamedPipe
- WriteFile
- Desconectar
- Repetir desde 2 a 4
Clie nt hace
- CreateFile
- ReadFile
El orden de ejecución es el siguiente,
- Servidor - CreateNamedPipe
- Client - CreateFile
- Servidor - - ConnectNamedPipe (debe regresar inmediatamente como cl ient ya está conectado)
- Servidor - escritura de archivo
- Cliente - ReadFile
- Servidor - DisconnectNamedPipe
- Cliente - CloseHandle
- Goto 2
Esto funciona muy bien para la primera hora. Sin embargo, el problema ocurre cuando el cliente intenta conectarse por segunda vez. Cuando el cliente intenta conectarse (CreateFile) por segunda vez antes de el servidor hizo ConnectNamedPipe (pero después de disconnectnamedpipe), obtiene ERROR_PIPE_BUSY. Funciona si el cliente llama a createfile después de que el servidor llame a ConnectNamedPipe.
¿Hay alguna forma de que pueda conectarme al cliente (CreateFile) antes del servidor llamado ConnectNamedPipe (después de DisconnectNamedPipe)?
código del servidor:
pipe_handle.pipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\testpipe1"),
PIPE_ACCESS_OUTBOUND |
FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFFER_SIZE, // output buffer size
BUFFER_SIZE, // input buffer size
2000, // client time-out
NULL);
if (pipe_handle.pipe == INVALID_HANDLE_VALUE) {
std::cout << "Error while creating pipe" << std::endl;
return -1;
}
std::cout <<"Connecting to named pipe" << std::endl;
std::cout<< "Somebody connected to named pipe" << std::endl;
int ac;
for (ac=0; ac<2; ac++) {
char a[25];
// Wait for some input. This helps me to start the client in other terminal.
cin >> a;
cout << "Connecting..." << endl;
ConnectNamedPipe(pipe_handle.pipe, 0);
cout << "Connect pipe returned." << endl;
// Wait for some input.
cin >> a;
string message = "Test message";
DWORD bytes_written;
if (!WriteFile(pipe_handle.pipe, message.c_str(), message.size(),
&bytes_written, NULL)) {
DWORD er = GetLastError();
char errs[200];
sprintf(errs, "Error : %ld", er);
std::cout << "Error communicating to client.";
std::cout << errs;
}
std::cout << "Written to pipe";
FlushFileBuffers(pipe_handle.pipe);
if (!DisconnectNamedPipe(pipe_handle.pipe)) {
std::cout << "Disconnect failed"<< GetLastError() << endl;
} else {
std::cout << "Disconnect successful"<<endl;
}
}
Código Cliente:
while (1) {
std::cout << "Returned" << std::endl;
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_READ,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
FILE_FLAG_OVERLAPPED, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY) {
std::cout<< "Could not open pipe " << GetLastError() << std::endl;
return -1;
}
// All pipe instances are busy, so wait for sometime.
if (! WaitNamedPipe(lpszPipename, NMPWAIT_USE_DEFAULT_WAIT)) {
std::cout<< "Could not open pipe: wait timed out." << std::endl;
}
}
OVERLAPPED ol1;
memset(&ol1, 0, sizeof(ol1));
ol1.Offset = 0;
ol1.OffsetHigh = 0;
ol1.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE events[1];
events[0] = ol1.hEvent;
cbToWrite = (lstrlen(message)+1)*sizeof(TCHAR);
DWORD bytes_to_read = 2000;
char * buf = reinterpret_cast<char *>(malloc(bytes_to_read));
DWORD bytes_read;
std::cout << "Waiting for read" << std::endl;
bool a = ReadFile(hPipe, buf, bytes_to_read, &bytes_read, &ol1);
if (! fSuccess) {
std::cout << "WriteFile to pipe failed. GLE " << GetLastError() << std::endl;
}
std::cout << "Waiting for multiple objects" << std::endl;
WaitForMultipleObjects(1, events, FALSE, INFINITE);
std::cout << "multiple objects returned" << std::endl;
printf("\nMessage sent to server");
CancelIo(hPipe);
CloseHandle(hPipe);
Gracias por la respuesta. Intenté con este código, pero el cliente sigue recibiendo ERROR_PIPE_BUSY. Una vez que el servidor llama a ConnectNamedPipe(), el cliente puede crear CreateFile() sin ningún error. – Ashwin
Se actualizó la pregunta sobre el código de servidor y cliente – Ashwin
@Ashwin: ver las ediciones para responder. –