Win32位API集支援的具名管道(named pipe)是實現網路處理序間通訊的一種有效手段。具名管道的介面比較簡單,在程式中實現比較方便,由其開發的應用程式也很容易使用,只要知道機器及管道的名稱即可串連兩台機器上的兩個進程。具名管道首先由一進程調用
CreateNamedPipe函數建立,這一建立具名管道的進程稱為Server進程,然後Server進程通過調用
ConnectNamedPipe函數等待一客戶相連。在管道的另一段,Client進程用
CreateFile函數或
CallNamedPipe函數開啟管道控制代碼,若無可用的管道執行個體,Client進程可調用
WaitNamedPipe函數等待。一旦串連成功,Client進程和Server進程可調用函數
ReadFile、
WriteFile或
ReadFileEx、
WriteileEx傳輸資訊。筆者在應用程式開發過程中,曾用具名管道方法做了實現網路兩處理序間通訊的一個小例子。這一例子實現了網路兩進程間文本的即時互編輯操作,即在任一台機器上對文本的修改可即時反映到另一台機器上,就好像這一修改是在另一台機器上進行的一樣。下面就對這一實驗程式作一介紹。程式分兩部分:Server部分和Client部分。文中只介紹與具名管道實現有關的內容。
Server
部分#define BUFSIZE 1280HANDLE hPipe;∥管道控制代碼BOOL FConnected;int Success=0;typedef struct Infor{DWORD Type;char Text[BUFSIZE-64];};∥資訊傳輸結構struct infor Info;∥包含編輯控制的對話方塊BOOL FAR PASCAL _export PipeServerDlg(HWND hDlg UINT message,WPARAM wParam,LPARAM IParam){UINT IdTimer,DWORD ret,dwMode;switch(message){case WM_INITDIALOG;IdTimer = SetTimer(hDlg,IdTimer,50,(TIMERPROC)NULL);∥Server建立具名管道hPipe = CreateNamedPipe("////.//pipe//buf",∥管道名PIPE_ACCESS_DUPLEX,∥雙向傳輸PIPE_WAIT|PIPE_TYPE_MESSAGE,∥阻塞模式,訊息流程管道PIPE_UNLIMITED_INSTANCES,,∥可以建立數目不限的管道執行個體
BUFSIZE,BUFSIZE,1000,NULL);If (hPipe!=INVALID_HANDLE_VALUE){∥管道控制代碼有效FConnected = ConnectNamedPipe(hPipe,NULL);∥等待串連If (FConected)Succes=1;∥串連成功Else{CloseHandle(hipe);Succes=0;}}if (Succes==1){ ∥若串連成功,將阻塞模式變為非阻塞模式;設定讀模式為訊息模式dwMode=PIPE_READMODE_MESSAGE|PIPE_NOWAIT;SetNamedPipeHandleState(hPipe,&dwMode,NULL,NULL);}return(TRUE);case WM_TIMER;if (Succes==1){ ∥若串連成功,定時讀管道資料Info.Type=-1;∥設初始值If (ReadFile(hPipe,(char*)&Info,sizeof(Infor),&ret,NULL)==TRUE){ ∥讀管道資料if (Info.Type==-2){ ∥收到對方結束對話方塊訊號,與對方同時結束對話方塊KillTimer(hDig,IdTimer); CloseHandle(hPipe); Succes=0;EndDialog(hDlg,TRUE); return(TRUE);}if (Info.Type==1)SetDlgItemText(hDlg,IDC_EDIT1,Info.Text);∥根據對方的變化修改編輯控制內容} }break;case WM_COMMAND;if (GET_WM_COMMAND_ID(wParam,lParam)==IDOK){ ∥結束對話方塊KillTimer(hDlg.IdTimer);If (Succes==1){Info.Type = -2;∥置結束對話方塊訊號WriteFile(hPipe,(char*)&Info,sizeof(Infor),&ret,NULL);∥寫資料到管道CloseHandle(hPipe);}Succes=0;EndDialog(hDlg,TRUE);return(TRUE);}if (Succes==1&& LOWORD(wParam)==IDC_EDIT1&& HIWORD(wParam)== EN_UPDATE){ ∥得到已修改的編輯控制中的內容,並寫入管道GetDlgItemText(hDlg,IDC_EDIT1,(LPSTR)(Info.Text),BUFSIZE-64);Info.Type=1;∥Info.Type=1:修改WriteFile(hPipe,(char*)&Info,sizeof(Infor),&ret,NULL);}break;}return(FALSE);}
Client
部分#define BUFSIZE 1280HANDLE hPipe∥管道控制代碼BOOL FConnected;int Succes=0,Flag=0; ∥資訊傳輸結構typedef struct Infor {DWORD Type;char Text[BUFSIZE-64];}; struct Infor Info;∥包含編輯控制的對話方塊BOOL FAR PASCAL __export PipeClientDlg(HWND hDlg,UINT message,WPARAM wParam, LPARAM lParam){UINT IdTimer;DWORD ret,dwMode;switch(message){case WM_INITDIALOG:IdTimer=SetTimer(hDlg,IdTimer,50,(TIMERPROC)NULL);return(TRUE);case WM_TIMER;if (Succes==0&&Flag==0){ ∥若未開啟管道控制代碼,定時作開啟操作∥Client開啟管道控制代碼hPipe = CreateFile("////ServerName//pipe//buf", ∥管道名,ServerName為運行伺服器處理序的機器名稱GENERIC_READ|GENERIC_WRITE, ∥讀/寫入模式0,∥檔案非共用NULL,OPEN_EXISTING,0,NULL);If (hPipe!=INVALID_HANDLE_VALUE){ ∥控制代碼有效Succes=1;Flag=1;}else{Flag=1;If (!WaitNamedPipe("////ServerName//pipe//buf",20000) ∥等待Flag=0; ClseSucces=1;}if (Succes==1){ ∥若串連成功,將阻塞模式變為非阻塞模式;設定讀模式為訊息模式dwMode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT;SetNamedPipeHandleState(hPipe,&dwMode,NULL,NULL);}}if(Succes==1){ ∥若串連成功,定時讀管道資料Info.Type=-1;∥設定初值If (ReadFile(hPipe,(char*)&Info,sizeof(Infor),&ret,NULL)==TRUE){if (Info1.Type==-2){ ∥收到對方結束對話方塊訊號,與對方同時結束對話方塊KillTimer(hDlg,IdTimer);CloseHandle(hPipe);Succes = 0;Flag = 0;EndDialog(hDlg,TRUE);return(TRUE);}if (Info.Type==1)SetDlgItemText(hDlg.IDC_EDIT1,Info.Text);}}break;case WM_COMMAND;if (GET_WM_COMMAND_ID(wParam,1Param)==IDOK){ ∥結束對話方塊KillTimer(hDlg,IdTimer);If (Succes==1){Info.Type = -2;WriteFile(hPipe,(char*)&Info,sizeof(Infor),&ret,NULL);CloseHandle(hPipe);}Succes = 0;Flag = 0;EndDialog(hDlg,TRUE);return(TRUE);}if(Succes==1&&LOWORD(wParam)==IDC_EDIT1&&HIWORD(wParam)==EN_UPDATE){GetDlgItemText(hDlg,IDC_ENIT1,(LPSTR)(Info.Text),BUFSIZE-64);Info.Type = 1;WriteFile(hPipe,(char*)&Info,sizeof(Infor),&ret,NULL);}break;}return(FALSE);}