windows管道使用

創建創建命名管道實例線程

代碼
1 // Handle of create Named Pipe thread.
2  HANDLE hThreadCreatePipes;
3
4  // Create Named Pipe thread .
5  hThreadCreatePipes = CreateThread(
6 NULL, // no security attribute
7   0, // default stack size
8   FUNCreatePipes, // thread proc
9   this, // thread parameter
10   0, // not suspended
11 NULL); // returns thread ID
12 // Close Handle.
13 CloseHandle(hThreadCreatePipes);
14 // Set handle null.
15 hThreadCreatePipes = NULL;

 

創建命名管道並創建監聽管道線程:    

代碼
1 DWORD WINAPI FUNCreatePipes(LPVOID lpParameter);
2 DWORD WINAPI FUNCreatePipes(LPVOID lpParameter)
3 {
4 BOOL fConnected = FALSE;
5 LPTSTR lpszPipename = TEXT("////.//pipe//MyPipe");
6
7 HANDLE hPipeServer;
8 HANDLE hThreadListenPipes;
9 while(TRUE)
10 {
11 hPipeServer = CreateNamedPipe(
12 lpszPipename, // pipe name
13 PIPE_ACCESS_DUPLEX, // read/write access
14 PIPE_TYPE_MESSAGE | // message type pipe
15 PIPE_READMODE_MESSAGE | // message-read mode
16 PIPE_WAIT, // blocking mode
17 PIPE_UNLIMITED_INSTANCES, // max. instances
18 BUFSIZ, // output buffer size
19 BUFSIZ, // input buffer size
20 0, // client time-out
21 NULL); // default security attribute
22
23 if (hPipeServer == INVALID_HANDLE_VALUE)
24 {
25 AfxMessageBox("Create named pipes failed.");
26 return -1;
27 }
28
29 // Wait for the client to connect; if it succeeds,
30 // the function returns a nonzero value. If the function
31 // returns zero, GetLastError returns ERROR_PIPE_CONNECTED.
32 fConnected = ConnectNamedPipe(hPipeServer, NULL);
33 if (fConnected)
34 {
35 // Create listen pipes thread.
36 hThreadListenPipes = CreateThread(
37 NULL, // no security attribute
38 0, // default stack size
39 FunListenPipes, // thread proc
40 hPipeServer, // thread parameter
41 0, // not suspended
42 NULL); // returns thread ID
43
44 // Close handle.
45 CloseHandle(hThreadListenPipes);
46 // Set handle null.
47 hThreadListenPipes = NULL;
48 }
49 else
50 {
51 // Close handle.
52 CloseHandle(hPipeServer);
53 // Set handle null.
54 hPipeServer = NULL;
55 }
56 }
57 return 0;
58 }


監聽管道,對管道數據進行讀取與回寫:

代碼
1 DWORD WINAPI FunListenPipes(LPVOID lpParameter);
2 DWORD WINAPI FunListenPipes(LPVOID lpParameter)
3 {
4 HANDLE hPipe = (HANDLE)lpParameter;
5
6 HANDLE hHeap = GetProcessHeap();
7 TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZ*sizeof(TCHAR));
8 TCHAR* pchReply = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZ*sizeof(TCHAR));
9
10 DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
11 BOOL fSuccess = FALSE;
12
13 CString strRequest = "";
14 CString strReply = "";
15 while (TRUE)
16 {
17 fSuccess = ReadFile(
18 hPipe, // handle to pipe
19 pchRequest, // buffer to receive data
20 BUFSIZ*sizeof(TCHAR), // size of buffer
21 &cbBytesRead, // number of bytes read
22 NULL); // not overlapped I/O
23
24 if (!fSuccess || cbBytesRead == 0)
25 {
26 break;
27 }
28
29 // Process the incoming message.
30 GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes);
31
32 // Write the reply to the pipe.
33 fSuccess = WriteFile(
34 hPipe, // handle to pipe
35 pchReply, // buffer to write from
36 cbReplyBytes, // number of bytes to write
37 &cbWritten, // number of bytes written
38 NULL); // not overlapped I/O
39
40 if (!fSuccess || cbReplyBytes != cbWritten)
41 {
42 break;
43 }
44
45 strRequest = pchRequest;
46 strReply = pchReply;
47 }
48
49 // Flush the pipe to allow the client to read the pipe's contents
50 // before disconnecting. Then disconnect the pipe, and close the
51 // handle to this pipe instance.
52 FlushFileBuffers(hPipe);
53 DisconnectNamedPipe(hPipe);
54 CloseHandle(hPipe);
55 hPipe = NULL;
56
57 HeapFree(hHeap, 0, pchRequest);
58 HeapFree(hHeap, 0, pchReply);
59
60 return 1;
61 }
62
63 VOID GetAnswerToRequest( LPTSTR pchRequest, LPTSTR pchReply, LPDWORD pchBytes )
64 {
65 // Check the outgoing message to make sure it's not too long for the buffer.
66 if (FAILED(strcpy(pchReply, pchRequest)))
67 {
68 *pchBytes = 0;
69 pchReply[0] = 0;
70 return;
71 }
72 *pchBytes = (lstrlen(pchReply)+1)*sizeof(TCHAR);
73 }


服務端採用阻塞模式等待客戶端的連接,客戶端連接成功後,立即繼續等待下一個客戶端的連接
並進行管道的監聽、管道數據的讀取與寫入。

以下爲客戶端實現:
初始化管道:

創建文件
1 CString strServerIP="This is the server ip";
2 CString lpPipeName="////" + strServerIP + "//pipe//MyPipe";
3 LPTSTR lpszPipename = new TCHAR[lpPipeName.GetLength()+1];
4 _tcscpy(lpszPipename, lpPipename);
5 HANDLE m_hPipeClient = CreateFile(
6 lpszPipename,
7 GENERIC_WRITE|GENERIC_READ,
8 0,
9 NULL,
10 OPEN_EXISTING,
11 0,
12 NULL);
13 if(m_hPipeClient == INVALID_HANDLE_VALUE)
14 {
15 CString strLastError;
16 strLastError.Format("%d",GetLastError());
17 AfxMessageBox("Error open pipes, the Last Error number is:"+strLastError);
18 return;
19 }
20 else
21 {
22 AfxMessageBox("Success open pipes");
23 }
24

 

設置管道狀態
1 DWORD dwMode = PIPE_READMODE_MESSAGE;
2 BOOL fSuccess = SetNamedPipeHandleState(
3 m_hPipeClient, // pipe handle
4 &dwMode, // new pipe mode
5 NULL, // don't set maximum bytes
6 NULL); // don't set maximum time
7 if ( ! fSuccess)
8 {
9 AfxMessageBox("Failed SetNamedPipeHandleState");
10 }

 

創建N個管道線程

 

讀寫管道
1 DWORD WINAPI FunSendReadData(LPVOID lpParameter);
2 DWORD WINAPI FunSendReadData(LPVOID lpParameter)
3 {
4 DWORD dwRead,dwWritten;
5 TCHAR chBuf[BUFSIZ];
6 BOOL fSuccess = FALSE;
7 DWORD cbRead, cbToWrite, cbWritten, dwMode;
8 LPTSTR lpvMessage=TEXT("This is the data sent.");
9
10 while(TRUE)
11 {
12 cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);
13 fSuccess = WriteFile(
14 pDlg->m_hPipeClient, // pipe handle
15 lpvMessage, // message
16 cbToWrite, // message length
17 &cbWritten, // bytes written
18 NULL);
19 if (!fSuccess)
20 {
21 break;
22 }
23
24 do
25 {
26 // Read from the pipe.
27 fSuccess = ReadFile(
28 pDlg->m_hPipeClient, // pipe handle
29 chBuf, // buffer to receive reply
30 BUFSIZ*sizeof(TCHAR), // size of buffer
31 &cbRead, // number of bytes read
32 NULL); // not overlapped
33
34 if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
35 {
36 break;
37 }
38
39 } while (!fSuccess); // repeat loop if ERROR_MORE_DATA
40 }
41 return 0;
42 }

 

 

服務端採用阻塞模式等待客戶端的連接,客戶端採用多個線程對管道進行數據讀寫。
因客戶端採用多個線程對管道進行讀寫,故一個線程讀取的數據可能並不是此線程寫入數據後,服務端讀取此線程剛寫入的數據後再寫入的數據。也就是客戶端多個線程寫入與讀取的數據可能會串,此理論已經過測試,爲解決此問題,可以在客戶端寫入數據時加標識,服務端讀取數據後,再寫入的數據帶上此標識,客戶端讀取時可根據此標識來判斷是否是寫入數據後服務端返回的消息。

作者:xinhaijulan
出處:http://xinhaijulan.cnblogs.com
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

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