调试出来了,准备用于父子进程之间的心跳,记录一下
服务端
#if 1
#include <Windows.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFSIZE 128
#define INSTANCES 8
#define PIPE_NAME "\\\\.\\pipe\\mynamedpipe"
#define PIPE_TIMEOUT 5000
#define PIPE_MSG_SRV "hi, clinet, i'm server."
#define PIPE_MSG_CLI "hi, server, i'm client."
typedef struct {
OVERLAPPED oOlp;
HANDLE hPipe;
DWORD cbRet;
DWORD dwRead;
CHAR chRead[BUFSIZE];
DWORD dwWrite;
CHAR chWrite[BUFSIZE];
DWORD dwState;
BOOL bIsPending;
} PIPEINST;
enum
{
CONNECTING_STATE = 0,
READING_STATE,
WRITING_STATE
};
DWORD dwPipeCnt;
static PIPEINST Pipe[INSTANCES];
static HANDLE hEvents[INSTANCES];
BOOL PipeConnect(int idx)
{
BOOL bOk;
BOOL bisPending = FALSE;
bOk = ConnectNamedPipe(Pipe[idx].hPipe, &Pipe[idx].oOlp);
if (bOk)
return FALSE;
switch (GetLastError())
{
case ERROR_IO_PENDING:
bisPending = TRUE;
break;
case ERROR_PIPE_CONNECTED:
if (SetEvent(Pipe[idx].oOlp.hEvent))
break;
default:
{
return 0;
}
}
return bisPending;
}
VOID PipeReconnect(DWORD i)
{
if (!DisconnectNamedPipe(Pipe[i].hPipe))
printf("DisconnectNamedPipe failed with %d.\n", GetLastError());
Pipe[i].bIsPending = PipeConnect(i);
Pipe[i].dwState = Pipe[i].bIsPending ? CONNECTING_STATE : READING_STATE;
}
INT PipeCreate()
{
INT idx = dwPipeCnt++;
HANDLE hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (hEvent == NULL)
return -1;
Pipe[idx].oOlp.hEvent = hEvents[idx] = hEvent;
Pipe[idx].hPipe = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, INSTANCES, BUFSIZE, BUFSIZE,
PIPE_TIMEOUT, NULL);
if (Pipe[idx].hPipe == INVALID_HANDLE_VALUE)
return -2;
Pipe[idx].bIsPending = PipeConnect(idx);
Pipe[idx].dwState = Pipe[idx].bIsPending ? CONNECTING_STATE : READING_STATE;
}
VOID PipeWait()
{
DWORD dwWait, cbRet;
INT idx;
BOOL bOk;
dwWait = WaitForMultipleObjects(dwPipeCnt, hEvents, FALSE, INFINITE);
idx = dwWait - WAIT_OBJECT_0;
if (idx < 0 || idx >= dwPipeCnt)
return ;
if (Pipe[idx].bIsPending) {
bOk = GetOverlappedResult(Pipe[idx].hPipe, &Pipe[idx].oOlp, &cbRet, FALSE);
printf("pending... %d %d %d\n", bOk, cbRet, GetLastError());
switch (Pipe[idx].dwState)
{
case CONNECTING_STATE:
if (!bOk)
return ;
Pipe[idx].dwState = READING_STATE;
break ;
case READING_STATE:
if (!bOk || cbRet == 0) {
PipeReconnect(idx);
return ;
}
Pipe[idx].dwRead = cbRet;
break;
case WRITING_STATE:
if (!bOk || cbRet != Pipe[idx].dwWrite) {
PipeReconnect(idx);
return ;
}
Pipe[idx].dwState = READING_STATE;
break;
default:
return ;
}
}
switch (Pipe[idx].dwState) {
case READING_STATE:
bOk = ReadFile(Pipe[idx].hPipe, Pipe[idx].chRead, BUFSIZE, &Pipe[idx].dwRead, &Pipe[idx].oOlp);
if (!bOk && GetLastError() == ERROR_IO_PENDING)
Pipe[idx].bIsPending = TRUE;
else if (!bOk)
PipeReconnect(idx);
else {
printf("recv: %s\n", Pipe[idx].chRead);
Pipe[idx].bIsPending = FALSE;
Pipe[idx].dwState = WRITING_STATE;
}
return;
case WRITING_STATE:
bOk = WriteFile(Pipe[idx].hPipe, PIPE_MSG_SRV, lstrlenA(PIPE_MSG_SRV), &cbRet, &Pipe[idx].oOlp);
if (!bOk && GetLastError() == ERROR_IO_PENDING)
Pipe[idx].bIsPending = TRUE;
else if (!bOk)
PipeReconnect(idx);
else if (bOk && cbRet == lstrlenA(PIPE_MSG_SRV)) {
printf("write msg: %s\n", PIPE_MSG_SRV);
Pipe[idx].bIsPending = FALSE;
Pipe[idx].dwState = READING_STATE;
}
else
printf("err %d\n", GetLastError());
break;
default:
break;
}
}
int main()
{
int idx = PipeCreate();
PipeReconnect(idx);
while (1) {
PipeWait();
}
}
#endif
客户端
#if 1
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUFSIZE 512
#define PIPE_CLI_MSG "hi, server, i'm cilnet."
#define PIPE_NAME "\\\\.\\pipe\\mynamedpipe"
char buf[256];
enum
{
PENDING,
WRITE,
READ
};
OVERLAPPED ov;
VOID PipeWait()
{
static HANDLE hPipe = INVALID_HANDLE_VALUE;
BOOL bOk;
DWORD cbRead, cbWrite;
DWORD dwMode;
static DWORD dwFlag = PENDING;
switch (dwFlag)
{
case PENDING:
printf("for pending\n");
if (hPipe != INVALID_HANDLE_VALUE) {
dwFlag = WRITE;
return;
}
hPipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE , 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
printf("wait pipe failed, error:%d\n", GetLastError());
if (hPipe != INVALID_HANDLE_VALUE) {
dwFlag = WRITE;
return;
}
if (GetLastError() == ERROR_PIPE_BUSY)
return;
bOk = WaitNamedPipeA(PIPE_NAME, 200);
if (!bOk) {
printf("wait pipe failed, error:%d\n", GetLastError());
return;
}
case WRITE:
printf("for write\n");
dwMode = PIPE_READMODE_MESSAGE;
bOk = SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL);
if (!bOk) {
printf("err set pipe, error: %d\n", GetLastError());
return;
}
bOk = WriteFile(hPipe, PIPE_CLI_MSG, lstrlenA(PIPE_CLI_MSG), &cbWrite, NULL);
if (!bOk || cbWrite != lstrlenA(PIPE_CLI_MSG))
break;
printf("write msg %s\n", PIPE_CLI_MSG);
dwFlag = READ;
return ;
case READ:
printf("for read\n");
do {
bOk = ReadFile(hPipe, buf, 256, &cbRead, &ov);
if (!bOk && GetLastError() == ERROR_IO_PENDING) {
break;
}
if (!bOk && GetLastError() != ERROR_MORE_DATA) {
break;
}
printf("read msg: %s\n", buf);
} while (!bOk);
dwFlag = WRITE;
default:
break;
}
}
int main()
{
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
while (1)
PipeWait();
return 0;
}
#endif