Sessão 2/2 – Named Pipes, overlapped IO, duplex
Comunicação assíncrona – overlapped I/O
operações que normalmente bloqueiam até completarem (read, write) podem ser completadas em background pelo SO
isto consegue-se passando um ponteiro não nulo para uma estrutura do tipo OVERLAPPED
se na estrutura for passado um handle para um evento, esse evento é assinalado quando a operação for completada pelo SO
//escritor.c 2ª versao #include <Windows.h> #include <tchar.h> #include <math.h> #include <stdio.h> #include <fcntl.h> #include <io.h> #include <time.h> #define PIPE_NAME TEXT("\\\\.\\pipe\\teste") #define TAM 256 #define PIPE_NMAX_INSTANCIAS 10 typedef struct { HANDLE hInstance; OVERLAPPED overlap; BOOL active; //se ja tem um cliente activo ou nao } PIPEDATA; PIPEDATA hPipes[PIPE_NMAX_INSTANCIAS]; HANDLE hEvents[PIPE_NMAX_INSTANCIAS], hMutex; int termina = 0; DWORD WINAPI ThreadMensagens(LPVOID param) { DWORD n; int i; TCHAR buf[TAM]; do { _tprintf(TEXT("[ESCRITOR] Frase: ")); _fgetts(buf, 256, stdin); buf[_tcslen(buf) - 1] = '\0'; WaitForSingleObject(hMutex, INFINITE); for (int i = 0; i < PIPE_NMAX_INSTANCIAS; i++) { if (hPipes[i].active) { if (!WriteFile(hPipes[i].hInstance, buf, _tcslen(buf) * sizeof(TCHAR), &n, NULL)) { _tprintf(TEXT("[ERRO] Escrever no pipe %d! (WriteFile)\n"),i); exit(-1); }else{ _tprintf(TEXT("[ESCRITOR] Enviei %d bytes ao leitor [%d]... (WriteFile)\n"), n, i); } } } ReleaseMutex(hMutex); } while (_tcscmp(buf, TEXT("fim"))); //terminar termina = 1; for (i = 0; i < PIPE_NMAX_INSTANCIAS; i++) { SetEvent(hEvents[i]); } return 0; } int _tmain(int argc, LPTSTR argv[]) { int i; int numClientes = 0; HANDLE hEventTemp, hPipeTemp, hThread; DWORD waitOffset, nbytes; #ifdef UNICODE _setmode(_fileno(stdin), _O_WTEXT); _setmode(_fileno(stdout), _O_WTEXT); #endif hMutex = CreateMutex(NULL, FALSE, NULL); if(hMutex == NULL) { _tprintf(TEXT("[ESCRITOR] Erro a criar o mutex\n")); exit(-1); } for (int i = 0; i < PIPE_NMAX_INSTANCIAS; i++) { _tprintf(TEXT("[ESCRITOR] Criar uma cópia %d do pipe '%s' ... (CreateNamedPipe)\n"), i, PIPE_NAME); hPipeTemp = CreateNamedPipe( PIPE_NAME, PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_NMAX_INSTANCIAS, //mais clientes 256 * sizeof(TCHAR), //update ou usar outro TCHAR buf[256]; 256 * sizeof(TCHAR), //update ou usar outro TCHAR buf[256]; 1000, NULL // ); if (hPipeTemp == INVALID_HANDLE_VALUE) { _tprintf(TEXT("[ERRO] Criar Named Pipe! (CreateNamedPipe)")); exit(-1); } _tprintf(TEXT("[ESCRITOR] Esperar ligação overlapped do leitor %d... (ConnectNamedPipe)\n"), i); hPipes[i].hInstance = hPipeTemp; hEventTemp = CreateEvent(NULL, TRUE, FALSE, NULL); if (hEventTemp == NULL) { _tprintf(TEXT("[ERRO] Criar Event! (CreateEvent)")); exit(-1); } ZeroMemory(&hPipes[i].overlap, sizeof(hPipes[i].overlap)); hEvents[i] = hEventTemp; hPipes[i].overlap.hEvent = hEvents[i]; if (ConnectNamedPipe(hPipeTemp, &hPipes[i].overlap) != 0) { //operação bloqueante até que aja um cliente _tprintf(TEXT("[ERRO] Ligação ao leitor! (ConnectNamedPipe\n")); exit(-1); } hPipes[i].active = FALSE; } hThread = CreateThread(NULL, 0, ThreadMensagens, NULL, 0, NULL); if (hThread == NULL) { _tprintf(TEXT("[ESCRITOR] Erro a criar o CreateThread\n")); exit(-1); } while(!termina && numClientes < PIPE_NMAX_INSTANCIAS) { _tprintf(TEXT("[ESCRITOR] Esperar pela ligçaão de leitor %d (WaitForMultipleObjects + GetOverlappedResult)\n"), numClientes); i = waitOffset - WAIT_OBJECT_0; _tprintf(TEXT("[ESCRITOR] Novo i = %d\n"), i); if(i>= 0 && i < PIPE_NMAX_INSTANCIAS) { ResetEvent(hEvents[i]); WaitForSingleObject(hMutex, INFINITE); _tprintf(TEXT("Ativar pipe %d\n"), i); hPipes[i].active = TRUE; ReleaseMutex(hMutex); numClientes++; } } WaitForSingleObject(hThread, INFINITE); _tprintf(TEXT("[ESCRITOR] Desligar o pipe (DisconnectNamedPipe)\n")); for (int i = 0; i < PIPE_NMAX_INSTANCIAS; i++) { if (!DisconnectNamedPipe(hPipes[i].hInstance)) { _tprintf(TEXT("[ERRO] Desligar o pipe! (DisconnectNamedPipe)")); exit(-1); } CloseHandle(hPipes[i].hInstance); } exit(0); }
encontrei mais informações sobre este exemplo em:
https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-server-using-overlapped-i-o
e a Comunicação bidirecional (duplex)
0 thoughts on “Sessão 2/2 – Named Pipes, overlapped IO, duplex”