C++:进程间通讯(部分转载,个人整理)

来源:互联网 发布:如何入驻天猫淘宝商城 编辑:程序博客网 时间:2024/06/10 01:45
/** * 主题:多线程和多进程技术 * */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 threadDWORD 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;}
0 0