windows編程學習——命名通道

命名管道數據傳輸過程:在服務器端調用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
);

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章