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”