管道的使用---參見Windows核心程式設計
阿新 • • 發佈:2018-11-03
管道也是一種重要的程序間通訊方式,最近看了Windows核心程式設計裡面關於管道的理論及例子,覺得挺有意思,自己模擬著寫了一個,其中有些還是不太明白
尤其是服務端中的WaitForSingleObjectEx函式的返回值---WAIT-IO-COMPLETION,歡迎大家指點;
測試時,可將編譯的程式複製一份,一個做客戶端,一個做服務端就可以,若要退出就在客戶端直接發出“quit",即可。
尤其是服務端中的WaitForSingleObjectEx函式的返回值---WAIT-IO-COMPLETION,歡迎大家指點;
測試時,可將編譯的程式複製一份,一個做客戶端,一個做服務端就可以,若要退出就在客戶端直接發出“quit",即可。
程式碼如下:
// ProcessCommunicate.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <windows.h> #define TEST_PIPE_NAME TEXT("\\\\.\\pipe\\MY_TEST_PIPE") //#define TEST_EVENT_NAME TEXT("Global\\EVENT_TEST_NAME") BOOL g_bExit = FALSE; struct OVERLAPPEDX { OVERLAPPED ov; TCHAR buf[1024]; HANDLE hPipe; }; void WINAPI CompleteReadRoutine(DWORD dwCode, DWORD dwBytesTrans, LPOVERLAPPED pOv); void WINAPI CompleteWriteRoutine(DWORD dwCode, DWORD dwBytesTrans, LPOVERLAPPED pOv); void FreeOverLappedX(OVERLAPPEDX** ppOv) { if (ppOv) { DisconnectNamedPipe((*ppOv)->hPipe); CloseHandle((*ppOv)->hPipe); GlobalFree(*ppOv); *ppOv = NULL; } } void RunAsClient() { BOOL bRet = WaitNamedPipe(TEST_PIPE_NAME, INFINITE); if (!bRet) { printf("WaitNamedPipe Fail, GetLastError:%d\n", GetLastError()); return; } HANDLE hFile = CreateFile(TEST_PIPE_NAME, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("Open Pipe Fail, GetLastError:%d\n", GetLastError()); return; } DWORD dwMode = PIPE_READMODE_MESSAGE; bRet = SetNamedPipeHandleState(hFile, &dwMode, NULL, NULL); if (!bRet) { printf("SetNamedPipeHandleState Fail, GetLastError:%d\n", GetLastError()); return; } DWORD dwWrite, dwRead; TCHAR buf[1024]={0}; Loop: printf("Please Input Message: "); memset(buf, 0, 1024*sizeof(TCHAR)); _tscanf(TEXT("%s"), buf); if (!WriteFile(hFile, buf, (_tcslen(buf)+1)*sizeof(TCHAR), &dwWrite, NULL)) { printf("WriteFile Fail, GetLastError:%d\n", GetLastError()); return; } if (_tcscmp(buf, TEXT("quit"))) { do { memset(buf, 0, 1024*sizeof(TCHAR)); bRet = ReadFile(hFile, buf, 1024*sizeof(TCHAR), &dwRead, NULL); } while (!bRet); _tprintf(TEXT("Client Recv: %s\n"), buf); goto Loop; } CloseHandle(hFile); } void WINAPI CompleteReadRoutine(DWORD dwCode, DWORD dwBytesTrans, LPOVERLAPPED pOv) { OVERLAPPEDX* pX = (OVERLAPPEDX*)pOv; _tprintf(TEXT("Server Recv: %s\n"), pX->buf); if (_tcscmp(pX->buf, TEXT("quit")) == 0) { g_bExit = TRUE; FreeOverLappedX(&pX); return; } HANDLE hPipe = pX->hPipe; if (hPipe == INVALID_HANDLE_VALUE) { printf("Open Pipe Fail!\n"); return; } printf("Please Reply: "); memset(pX->buf, 0, 1024*sizeof(TCHAR)); _tscanf(TEXT("%s"), pX->buf); if (!WriteFileEx(hPipe, pX->buf, (_tcslen(pX->buf)+1)*sizeof(TCHAR), pOv, CompleteWriteRoutine)) { printf("WriteFileEx Fail %d\n", GetLastError()); FreeOverLappedX(&pX); } } void WINAPI CompleteWriteRoutine(DWORD dwCode, DWORD dwBytesTrans, LPOVERLAPPED pOv) { OVERLAPPEDX* pX = (OVERLAPPEDX*)pOv; HANDLE hPipe = pX->hPipe; if (hPipe == INVALID_HANDLE_VALUE) { printf("Open Pipe Fail!\n"); return; } memset(pX->buf, 0, 1024*sizeof(TCHAR)); if (!ReadFileEx(hPipe, pX->buf, 1024*sizeof(TCHAR), pOv, CompleteReadRoutine)) { printf("ReadFileEx Fail %d\n", GetLastError()); FreeOverLappedX(&pX); } } void RunAsServer() { HANDLE hPipe; BOOL bIOIng, bOk, bFlag; DWORD dwErr, dwRet, dwWait; //OVERLAPPED OVERLAPPED ov; ov.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); OVERLAPPEDX* pX = NULL; //CREATENAMEDPIPE Loop: hPipe = CreateNamedPipe(TEST_PIPE_NAME, PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 5000, NULL); if (hPipe == INVALID_HANDLE_VALUE) { printf("Server Pipe Create Fail!\n"); return; } //CONNECT bIOIng = FALSE; bOk = ConnectNamedPipe(hPipe, &ov); dwErr = GetLastError(); if (bOk) { printf("ConnectNamedPipe Fail GetLastError : %d!\n", dwErr); return; } switch (dwErr) { case ERROR_IO_PENDING: bIOIng = TRUE; break; case ERROR_PIPE_CONNECTED: if (SetEvent(ov.hEvent)) break; default: printf("ConnectNamedPipe Fail GetLastError: %d!\n", dwErr); break; } bFlag = TRUE; while (!g_bExit) { dwWait = WaitForSingleObjectEx(ov.hEvent, INFINITE, TRUE); switch (dwWait) { case WAIT_OBJECT_0: //Event Signal Or IO pending if (bIOIng) { //Pending if (!GetOverlappedResult(hPipe, &ov, &dwRet, FALSE)) { printf("GetOverlappedResult Fail %d!\n", GetLastError()); return; } } printf("Client Has Connect!\n"); //IO Over if (bFlag) { pX = (OVERLAPPEDX*)GlobalAlloc(GPTR, sizeof(OVERLAPPEDX)); if (!pX) { printf("GlobalAlloc Fail GetLastError: %d\n", GetLastError()); return; } memset(pX, 0, sizeof(OVERLAPPEDX)); pX->hPipe = hPipe; CompleteWriteRoutine(0, 0, (OVERLAPPED*)pX); goto Loop; } case WAIT_IO_COMPLETION: //printf("Server WAIT_IO_COMPLETION!\n"); break; default: printf("WaitForSingleObjectEx Fail GetLastError: %d\n", dwErr); return; } } printf("Server Exit!\n"); } int _tmain(int argc, _TCHAR* argv[]) { char mode; Loop: printf("Command As Following:\n 1 -- Client Mode \n 2 -- Server Mode \n q -- Quit \nPlease select : "); scanf("%c", &mode); if (mode == 10) { scanf("%c", &mode); } switch (mode) { case '1': printf("Run As Client!\n"); RunAsClient(); break; case '2': printf("Run As Server!\n"); RunAsServer(); break; case 'q': break; default: printf("Invalid mode!\n"); goto Loop; } system("@pause"); return 0; }