/**
* 主題:多線程和多進程技術
*
*/
Q1: C++進程間通訊的方式
管道(命名管道,匿名管道),socket,事件event,共享內存,消息隊列
實例:命名管道實例
/**
* 方案如下所示
* 管道服務端:CreateNamedPipe(創建管道HANDLE hPipe) -> ConnectNamedPipe(連接客戶端)-> (WriteFile)往管道寫數據/(readFile)往管道讀數據
* 管道客戶端: WaitNamedPipe(等待命名管道實例有效,設置超時時間) -> CreateFile(打開管道,返回命名管道句柄) -> (WriteFile)往管道寫數據/(readFile)往管道讀數據
* 小結:api函數:CreateNamePipe,ConnectNamedPipe,WaitNamedPipe.CreateFile,WriteFile,ReadFile
*/
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <ctime>
int main(int argc,_TCHAR *argv[])
{
srand(time(NULL));
char buf[256] = "";
DWORD rlen = 0;
HANDLE hPipe = CreateNamedPipe(
TEXT("\\\\.\\Pipe\\mypipe"), //管道名
PIPE_ACCESS_DUPLEX, //管道類型
PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, //管道參數
PIPE_UNLIMITED_INSTANCES, //管道能創建的最大實例數量
0, //輸出緩衝區長度 0表示默認
0, //輸入緩衝區長度 0表示默認
NMPWAIT_WAIT_FOREVER, //超時時間
NULL);
if(INVALID_HANDLE_VALUE == hPipe)
{
printf("Create Pipe Error(%d)\n",GetLastError());
}
// 創建命名管道成功
else
{
//阻塞等待客戶端連接
printf("Waiting For Client Connection...\n");
if(ConnectNamedPipe(hPipe,NULL) == null)
{
printf("Connection failed!\n");
}
else
{
printf("Connection Success!\n");
}
// 進程間數據通訊
while(true)
{
// 接收客戶端發送過來的內容
if(ReadFile(hPipe,buf,256,&rlen,NULL) == FALSE)
{
printf("Read Data From Pipe Failed!\n");
break;
}
// 向客戶端發送內容
else
{
printf("From Client: data = %s, size = %d\n", buf, rlen);
char wbuf[256] = "";
sprintf(wbuf, "%s%d", wbuf, rand()%1000);
DWORD wlen = 0;
WriteFile(hPipe,wbuf,sizeof(buf),&wlen,0);
printf("To Client: data = %s, size = %d\n", wbuf, wlen);
Sleep(1000);
}
}
CloseHandle(hPipe); // 關閉管道
}
system("PAUSE");
}
// 命名管道客戶端
#include "stdafx.h"
02.#include <stdio.h>
03.#include <windows.h>
04.#include <ctime>
05.
06.int main(int argc, _TCHAR* argv[])
07.{
08. srand(time(NULL));
09.
10. DWORD wlen = 0;
11. Sleep(1000);//等待pipe的創建成功!
12.
13. BOOL bRet = WaitNamedPipe(TEXT("\\\\.\\Pipe\\mypipe"), NMPWAIT_WAIT_FOREVER);
14.
15. if (!bRet)
16. {
17. printf("connect the namedPipe failed!\n");
18. return 0;
19. }
20.
21. HANDLE hPipe=CreateFile( //管道屬於一種特殊的文件
22. TEXT("\\\\.\\Pipe\\mypipe"), //創建的文件名
23. GENERIC_READ | GENERIC_WRITE, //文件模式
24. 0, //是否共享
25. NULL, //指向一個SECURITY_ATTRIBUTES結構的指針
26. OPEN_EXISTING, //創建參數
27. FILE_ATTRIBUTE_NORMAL, //文件屬性(隱藏,只讀)NORMAL爲默認屬性
28. NULL); //模板創建文件的句柄
29.
30. if (INVALID_HANDLE_VALUE == hPipe)
31. {
32. printf("open the exit pipe failed!\n");
33. }
34. else
35. {
36. while(true)
37. {
38. char buf[256] = "";
39. sprintf(buf,"%s%d",buf,rand()%1000);
40. if(WriteFile(hPipe,buf,sizeof(buf),&wlen,0)==FALSE) //向服務器發送內容
41. {
42. printf("write to pipe failed!\n");
43. break;
44. }
45. else
46. {
47. printf("To Server: data = %s, size = %d\n", buf, wlen);
48. char rbuf[256] = "";
49. DWORD rlen = 0;
50. ReadFile(hPipe, rbuf, sizeof(rbuf), &rlen, 0); //接受服務發送過來的內容
51. printf("From Server: data = %s, size = %d\n", rbuf, rlen);
52. }
53. Sleep(1000);
54. }
55. CloseHandle(hPipe);//關閉管道
56. }
57.
58. system("PAUSE");
59. return 0;
60.}
實例:socket(此處代碼重點在互斥體,實現對共享資源的訪問保護)
ex:socket的客戶端,多線程實例,訪問共享資源
#include <iostream>
#include <Winsock2.h>
#include <list>
#include <string>
#include <cstdio>
#paramea comment(lib,"Ws2_32.lib")
using namespace std;
/**
* @:全局變量,供多個子線程訪問
*/
list<string> str_a;
list<string> str_b;
list<string> str_c;
/**
* @:加鎖訪問共享資源(互斥鎖)
*/
HANDLE Lock(LPCWSTR name)
{
HANDLE mutex;
// 首先訪問互斥鎖,獲取互斥體對象句柄(openmutex)。若失敗則創建互斥對象,否則等待獲取此互斥對象的控制權(WaitForSingleObject)
mutext = openmutex(MUTEXT_ALL_ACCESS,FALSE,name);
if(NULL == mutext)
{
mutex = CreateMutex(NULL,TURE,name);
}
else
{
/**
* WaitForSingleObject函數用來檢測hHandle事件的信號狀態,在某一線程中調用該函數時,線程暫時掛起,如果在掛起的dwMilliseconds毫秒內,線程所等待的對象變爲有信號狀態,則該函數立即返回;
*/
WaitForSingleObject(hMutex,INFINITE);
}
return mutex;
}
/**
* @:釋放互斥鎖,供其他線程可訪問共享資源
*/
bool Unlock(HANDLE mutex)
{
// 釋放互斥體對象的控制權
if(0 == ReleaseMutex(mutex))
{
return false;
}
else
{
CLoseHandle(mutex);
mutex = NULL;
return true;
}
}
// socket client thread
DWORD WINAPI ClientThread(LPVOID lpParameter)
{
SOCKET ClientSocket = (SOCKET)lpParameter;
char recvBuf[1000];
while(true)
{
memset(recvBuf,0x00,sizeof(recvBuf));
recv(ClientSocket,recvBuf,sizeof(recvBuf),0);
HANDL mutex_a,mute_b,mutex_c;
mutex_a = Lock( L"mutex");
str_a.push_back(string(recvBuf));
UnLock(mutex_a);
mutex_b= Lock(L"mutex");
str_b.push_back(streing(recvBuf));
Unlock(mutex_b);
mutex_c = Lock(L"mutex");
str_c.push_back(string(recvBuf));
Unlock(mutex_c);
}
return 0;
}
DWORD WINAPI AProcess(LPVOID lpParametr)
{
while(true)
{
HANDLE mutex = Lock(L"mutex");
if(!str_a.empty())
{
string str = str_a.front();
str_a.pop_front();
printf("A: %s\n", str.c_str());
}
Unlock(mutex);
}
}
DWORD WINAPI BProccess(LPVOID lpParameter)
{
while(true)
{
HANDLE mutex = Lock(L"mutex");
if (!str_b.empty())
{
string str = str_b.front();
str_b.pop_front();
printf("B: %s\n", str.c_str());
}
Unlock(mutex);
}
}
DWORD WINAPI CProccess(LPVOID lpParameter)
{
while(true)
{
HANDLE mutex = Lock(L"mutex");
if (!str_c.empty())
{
string str = str_c.front();
str_c.pop_front();
printf("C: %s\n", str.c_str());
}
Unlock(mutex);
}
}
int main()
{
// 加載socket動態鏈接庫(dll)
WORD wVersionRequested;
WSADATA wsaData; // 這結構是用於接收Wjndows Socket的結構信息的
int err;
wVersionRequested = MAKEWORD( 1, 1 ); // 請求1.1版本的WinSock庫
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return -1; // 返回值爲零的時候是表示成功申請WSAStartup
}
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
// 檢查這個低字節是不是1,高字節是不是1以確定是否我們所請求的1.1版本
// 否則的話,調用WSACleanup()清除信息,結束函數
WSACleanup( );
return -1;
}
// 創建socket操作,建立流式套接字,返回套接字號sockClient
// SOCKET socket(int af, int type, int protocol);
// 第一個參數,指定地址簇(TCP/IP只能是AF_INET,也可寫成PF_INET)
// 第二個,選擇套接字的類型(流式套接字),第三個,特定地址家族相關協議(0爲自動)
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
// 將套接字sockClient與遠程主機相連
// int connect( SOCKET s, const struct sockaddr* name, int namelen);
// 第一個參數:需要進行連接操作的套接字
// 第二個參數:設定所需要連接的地址信息
// 第三個參數:地址的長度
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 本地迴路地址是127.0.0.1;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8000);
connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
HANDLE hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sockClient, 0, NULL);
HANDLE hThread_a = CreateThread(NULL, 0, AProccess, (LPVOID)NULL, 0, NULL);
HANDLE hThread_b = CreateThread(NULL, 0, BProccess, (LPVOID)NULL, 0, NULL);
HANDLE hThread_c = CreateThread(NULL, 0, CProccess, (LPVOID)NULL, 0, NULL);
while(true);
printf("End linking...\n");
closesocket(sockClient);
WSACleanup(); // 終止對套接字庫的使用
printf("\n");
system("pause");
return 0;
}
C++:進程間通訊(部分轉載,個人整理)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.