/**
* 主题:多线程和多进程技术
*
*/
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
#include
#include
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
03.#include
04.#include
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
#include
#include
#include
#include
#paramea comment(lib,"Ws2_32.lib")
using namespace std;
/**
* @:全局变量,供多个子线程访问
*/
list str_a;
list str_b;
list 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;
}