命名管道數據傳輸過程:在服務器端調用CreateNamedpipe創建命名管道之後,調用ConnectNamedpipe函數讓服務器端進程等待客戶端進程連接到該命名管道的實例上。
在客戶端首先調用WaiteNamedpipe函數判斷當前是否有可以利用的命名管道實例,如果有,就調用CreateFile函數打開該命名管道的實例,並且建立一個連接。
下面是一些函數,以及一個具體實例
服務器端程序:
#include <stdio.h>
#include <Windows.h>
#define PIPENAME0 "//./Pipe/Test" //管道名
#define MAXDATANUM 1024
int main()
{
DWORD ReadNum = 0; //DWORD 表示32位字節無符號整數這裏定義了服務器讀入的字節數ReadNum初始爲0 Windows下經常用來保存地址(或者存放指針)
char buffer[MAXDATANUM];//定義一個char類型的數組存放讀取的數據
HANDLE g_hPipe = INVALID_HANDLE_VALUE;//HANDLE是專門定義句柄的標示符 定義了一個名爲g_hPipe的句柄爲無效句柄值
printf("Server of name pipe is testing..........\n");
//創建名稱爲Test的命名管道
g_hPipe = CreateNamedPipe(PIPENAME0,PIPE_ACCESS_DUPLEX,PIPE_READMODE_BYTE,2,0,0,1000,NULL); //g_hPipe表示管道句柄
// 參數1 PIPENAME0 表示管道的名稱 參數2 PIPE_ACCESS_DUPLEX 表示管道創建好後的打開模式即標誌以雙向傳輸方式打開一個管道(雙工通信)
//參數3 PIPE_READMODE_BYTE 命名管道提供以字節方式通信 參數4 “2”表示管道內的最大實例數 參數“0”,“0”,“1000”,“NULL”分別表示輸出緩存大小、輸入緩存大小、超時設置、安全屬性的指針
if (INVALID_HANDLE_VALUE == g_hPipe)
{
printf("Create name pipe is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}//判斷句柄是否有效如果無效調用CloseHandle函數關閉句柄
printf("Waiting connect......\n");
if (FALSE == ConnectNamedPipe(g_hPipe,NULL))
{
printf("Connect is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}//判斷客戶端與管道是否連接若未連接則關閉管道
printf("Connect is successful......\n");
printf("Read data is starting......\n");//連接成功輸出......
while(1)
{
memset(buffer,0,MAXDATANUM);//將buffer數組中所有字符清零
if (!(ReadFile(g_hPipe,&buffer,sizeof(buffer),&ReadNum,NULL)))//判斷讀取操作是否成功 ReadFile作用:從文件指針指向的位置開始將數據讀出到一個文件中
{
printf("Read data is closing......\n");
CloseHandle(g_hPipe); //關閉管道句柄
getchar();
return 0;
}
printf("Receive data is %s\n",buffer); //打印出接收的數據
Sleep(100);//執行掛起操作
}
CloseHandle(g_hPipe);//數據傳輸完成後關閉管道
getchar();
return 0;
}
PIPENAME0 "//./Pipe/Test" //管道名
#define MAXDATANUM 1024
int main()
{
DWORD ReadNum = 0; //DWORD 表示32位字節無符號整數這裏定義了服務器讀入的字節數ReadNum初始爲0 Windows下經常用來保存地址(或者存放指針)
char buffer[MAXDATANUM];//定義一個char類型的數組存放讀取的數據
HANDLE g_hPipe = INVALID_HANDLE_VALUE;//HANDLE是專門定義句柄的標示符 定義了一個名爲g_hPipe的句柄爲無效句柄值
printf("Server of name pipe is testing..........\n");
//創建名稱爲Test的命名管道
g_hPipe = CreateNamedPipe(PIPENAME0,PIPE_ACCESS_DUPLEX,PIPE_READMODE_BYTE,2,0,0,1000,NULL); //g_hPipe表示管道句柄
// 參數1 PIPENAME0 表示管道的名稱 參數2 PIPE_ACCESS_DUPLEX 表示管道創建好後的打開模式即標誌以雙向傳輸方式打開一個管道(雙工通信)
//參數3 PIPE_READMODE_BYTE 命名管道提供以字節方式通信 參數4 “2”表示管道內的最大實例數 參數“0”,“0”,“1000”,“NULL”分別表示輸出緩存大小、輸入緩存大小、超時設置、安全屬性的指針
if (INVALID_HANDLE_VALUE == g_hPipe)
{
printf("Create name pipe is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}//判斷句柄是否有效如果無效調用CloseHandle函數關閉句柄
printf("Waiting connect......\n");
if (FALSE == ConnectNamedPipe(g_hPipe,NULL))
{
printf("Connect is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}//判斷客戶端與管道是否連接若未連接則關閉管道
printf("Connect is successful......\n");
printf("Read data is starting......\n");//連接成功輸出......
while(1)
{
memset(buffer,0,MAXDATANUM);//將buffer數組中所有字符清零
if (!(ReadFile(g_hPipe,&buffer,sizeof(buffer),&ReadNum,NULL)))//判斷讀取操作是否成功 ReadFile作用:從文件指針指向的位置開始將數據讀出到一個文件中
{
printf("Read data is closing......\n");
CloseHandle(g_hPipe); //關閉管道句柄
getchar();
return 0;
}
printf("Receive data is %s\n",buffer); //打印出接收的數據
Sleep(100);//執行掛起操作
}
CloseHandle(g_hPipe);//數據傳輸完成後關閉管道
getchar();
return 0;
}
服務器端:
(1)創建命名管道函數CreateNamedPipe
原型 HANDLE CreateNamedPipe(
LPCTSTR lpName, // 指向管道名稱的指針
DWORD dwOpenMode, // 管道打開模式
DWORD dwPipeMode, // 管道模式
DWORD nMaxInstances, // 最大實例數
DWORD nOutBufferSize, // 輸出緩存大小
DWORD nInBufferSize, // 輸入緩存大小
DWORD nDefaultTimeOut, // 超時設置
LPSECURITY_ATTRIBUTES lpSecurityAttributes // 安全屬性指針
);
(2) 在命名管道實例上監聽客戶機連接請求的函數ConnectNamedPipe
原型:ConnectNamedPipe(
HANDLE hNamedPipe,
LPOVERLAPPED lpOverlapped
);
參數含義:
hNamedPipe:管道的句柄
lpOverlapped ,如果設爲NULL(傳遞ByVal As Long),表示將線程掛起,直到一個客戶端同管道連接爲止。
否則就立即返回;此時,如果管道尚未連接,客戶同管道連接時就會觸發lpOverlapped結構中的事件對象。隨後,可用一個等待函數來監視連接
(3)從客戶機接收數據函數ReadFile:
原型:BOOL ReadFile(
HANDLE hFile, //文件的句柄
LPVOID lpBuffer, //用於保存讀入數據的一個緩衝區
DWORD nNumberOfBytesToRead, //要讀入的字節數
LPDWORD lpNumberOfBytesRead,//指向實際讀取字節數的指針
LPOVERLAPPED lpOverlapped //如文件打開時指定了FILE_FLAG_OVERLAPPED,那麼必須用這個參數引用一個特殊的結構。該結構定義了一次異步讀取操作。否則,應將這個參數設爲NULL
);
(4)關閉命名管道實例句柄函數CloseHandle:
CloseHandle(
__in HANDLE hObject //代表一個已打開對象句柄
);
(5)memset函數
void *memset(void *s, int ch, size_t n);函數解釋:將s中前n個字節替換爲ch並返回s
memset功能:是在一段內存塊中填充某個給定的值,它是對較大的結構體或數組進行清零操作的一種最快方法。
客戶端:
#include <stdio.h>
#include <Windows.h>
#define PIPENAME0 "//./Pipe/Test" //管道名
#define MAXDATANUM 1024
int main()
{
DWORD ReadNum = 0; //DWORD 表示32位字節無符號整數這裏定義了服務器讀入的字節數ReadNum初始爲0 Windows下經常用來保存地址(或者存放指針)
char buffer[MAXDATANUM];//定義一個char類型的數組存放讀取的數據
HANDLE g_hPipe = INVALID_HANDLE_VALUE;//HANDLE是專門定義句柄的標示符 定義了一個名爲g_hPipe的句柄爲無效句柄值
printf("Server of name pipe is testing..........\n");
//創建名稱爲Test的命名管道
g_hPipe = CreateNamedPipe(PIPENAME0,PIPE_ACCESS_DUPLEX,PIPE_READMODE_BYTE,2,0,0,1000,NULL); //g_hPipe表示管道句柄
// 參數1 PIPENAME0 表示管道的名稱 參數2 PIPE_ACCESS_DUPLEX 表示管道創建好後的打開模式即標誌以雙向傳輸方式打開一個管道(雙工通信)
//參數3 PIPE_READMODE_BYTE 命名管道提供以字節方式通信 參數4 “2”表示管道內的最大實例數 參數“0”,“0”,“1000”,“NULL”分別表示輸出緩存大小、輸入緩存大小、超時設置、安全屬性的指針
if (INVALID_HANDLE_VALUE == g_hPipe)
{
printf("Create name pipe is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}//判斷句柄是否有效如果無效調用CloseHandle函數關閉句柄
printf("Waiting connect......\n");
if (FALSE == ConnectNamedPipe(g_hPipe,NULL))
{
printf("Connect is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}//判斷客戶端與管道是否連接若未連接則關閉管道
printf("Connect is successful......\n");
printf("Read data is starting......\n");//連接成功輸出......
while(1)
{
memset(buffer,0,MAXDATANUM);//將buffer數組中所有字符清零
if (!(ReadFile(g_hPipe,&buffer,sizeof(buffer),&ReadNum,NULL)))//判斷讀取操作是否成功 ReadFile作用:從文件指針指向的位置開始將數據讀出到一個文件中
{
printf("Read data is closing......\n");
CloseHandle(g_hPipe); //關閉管道句柄
getchar();
return 0;
}
printf("Receive data is %s\n",buffer); //打印出接收的數據
Sleep(100);//執行掛起操作
}
CloseHandle(g_hPipe);//數據傳輸完成後關閉管道
getchar();
return 0;
}
1)呼叫對服務器的連接函數CreateFile:
原型:HANDLE WINAPI CreateFile(
_In_ LPCTSTR lpFileName,//要打開的文件的名字
_In_ DWORD dwDesiredAccess,//設備訪問方式比如:GENERIC_READ或者是GENERIC_WRITE
_In_ DWORD dwShareMode,//共享方式 表示只能接受一個客戶端的請求的到來 不需要共享
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//安全特性NULL
_In_ DWORD dwCreationDisposition,//設置文件操作的要求 在打開一個通信端口時如管道,無論如何都要設置成 OPEN_EXISTING打開現有的管道
_In_ DWORD dwFlagsAndAttributes,//文檔屬性 FELE_ATTRIBUTE_NORMAL
_In_opt_ HANDLE hTemplateFile //模板文件 如果不爲零,則指定一個文件句柄。新文件將從這個文件中複製擴展屬性
);
函數功能:這是一個多功能的函數,可打開或創建以下對象,並返回可訪問的句柄
參數類型及說明
lpFileName String,要打開的文件的名字
dwDesiredAccessLong,如果爲 GENERIC_READ 表示允許對設備進行讀訪問;如果爲 GENERIC_WRITE 表示允許對設備進行寫訪問(可組合使用);如果爲零,表示只允許獲取與一個設備有關的信息
dwShareMode Long,零表示不共享; FILE_SHARE_READ 和/或 FILE_SHARE_WRITE 表示允許對文件進行共享訪問
lpSecurityAttributes SECURITY_ATTRIBUTES,指向一個SECURITY_ATTRIBUTES結構的指針,定義了文件的安全特性
dwCreationDisposition Long,下述常數之一:
CREATE_NEW 創建文件;如文件存在則會出錯
CREATE_ALWAYS 創建文件,會改寫前一個文件
OPEN_EXISTING 文件必須已經存在。由設備提出要求
OPEN_ALWAYS 如文件不存在則創建它
TRUNCATE_EXISTING 將現有文件縮短爲零長度
dwFlagsAndAttributesLong,一個或多個下述常數
FILE_ATTRIBUTE_ARCHIVE 標記歸檔屬性
FILE_ATTRIBUTE_COMPRESSED 將文件標記爲已壓縮,或者標記爲文件在目錄中的默認壓縮方式
FILE_ATTRIBUTE_NORMAL 默認屬性
FILE_ATTRIBUTE_HIDDEN 隱藏文件或目錄
FILE_ATTRIBUTE_READONLY 文件爲只讀
FILE_ATTRIBUTE_SYSTEM 文件爲系統文件
FILE_FLAG_WRITE_THROUGH操作系統不得推遲對文件的寫操作
FILE_FLAG_OVERLAPPED 允許對文件進行重疊操作
FILE_FLAG_NO_BUFFERING 禁止對文件進行緩衝處理。文件只能寫入磁盤卷的扇區塊
FILE_FLAG_RANDOM_ACCESS 針對隨機訪問對文件緩衝進行優化
FILE_FLAG_SEQUENTIAL_SCAN針對連續訪問對文件緩衝進行優化
FILE_FLAG_DELETE_ON_CLOSE 關閉了上一次打開的句柄後,將文件刪除。特別適合臨時文件
也可在Windows NT下組合使用下述常數標記:
SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY
hTemplateFile Long,相當於一個模板,如果不爲零,則指定一個文件句柄。新文件將從這個文件中複製擴展屬性即相當於拷貝的功能
(2)WriteFile將數據發給客戶機
BOOL WriteFile(
HANDLE hFile, // 文件句柄
LPCVOID lpBuffer,// 數據緩存區指針
DWORD nNumberOfBytesToWrite,// 你要寫的字節數
LPDWORD lpNumberOfBytesWritten, // 用於保存實際寫入字節數的存儲區域的指針
LPOVERLAPPED lpOverlapped // OVERLAPPED結構體指針 如果文件是以FILE_FLAG_OVERLAPPED方式打開的話,那麼這個指針就不能爲NULL
);