• win下命名管道通信压力测试实现(含c++示例代码)


    目录

    一、关于命名管道概述

    二、命名管道测试实现

    三、编译实现

    四、补充


    一、关于命名管道概述

           管道是一个有两端的对象。一个进程向管道写入信息,而另外一个进程从管道读取信息。进程可以从这个对象的一个端口写数据,从另一个端口读数据。创建管道的进程称为管道服务器(Pipe Server),而连接到这个管道的进程称为管道客户端(Pipe Client)。
            在 Windows 系统中,存在两种类型的管道: “匿名管道”(Anonymous pipes)和“命名管道”(Named pipes)。匿名管道是基于字符和半双工的(即单向);命名管道是面向消息和全双工的,同时还允许网络通信,用于创建客户端/服务器系统。

            匿名管道:单向通信,只能本地使用。由于匿名管道单向通信,且只能在本地使用的特性,一般用于程序输入输出的重定向,如一些后门程序获取 cmd 内容等等。

            命名管道是一个具有名称,可在同一台计算机的不同进程之间或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信管道。命名管道的所有实例拥有相同的名称,但是每个实例都有其自己的缓冲区和句柄,用来为不同客户端提供独立的管道。任何进程都可以访问命名管道,并接受安全权限的检查,通过命名管道使相关的或不相关的进程之间的通讯变得异常简单。

    二、命名管道测试实现

            win c++标准函数中,已提供了CreateNamedPipe、ConnectNamedPipe、WriteFile、ReadFile、CloseHandle等创建、连接、使用、关闭的管道操作函数,本测试中,将建立进可能多的线程,对通一命名管道进行大量、快速的读写操作。

            本次测试将创建一个管道,并创建ipc服务端接收数据和ipc客户端发送数据,同时有300百个线程对管道进行数据写入及读取操作,测试完成10万次数据写入及读取操作,看看是否其管道通信效率如何。

            本文采用vs2010+cmake完成编译测试,测试代码目录结构如下:

    1. ipc_test
    2. bin
    3. build
    4. ipc
    5. ipcclient.h
    6. ipcclient.cpp
    7. ipcserver.h
    8. ipcserver.cpp
    9. src
    10. main.cpp
    11. CMakeLists.txt

            ipcclient.h

          

    1. #ifndef _IPC_CLIENT_H_
    2. #define _IPC_CLIENT_H_
    3. #include
    4. class IPCClient
    5. {
    6. public:
    7. IPCClient(int n);
    8. ~IPCClient();
    9. int WriteInfo(char *, DWORD , DWORD* );
    10. int ReadInfo(char *, DWORD , DWORD* );
    11. private:
    12. bool Connect();
    13. private:
    14. int _nID;
    15. HANDLE _hPipe;
    16. bool _bConnected;
    17. };
    18. #endif // _IPC_CLIENT_H_

    ipcclient.cpp实现管道打开连接、数据写入操作,管道名称和服务端保持一致,例如"\\\\.\\pipe\\pyfree"。

    1. #include "ipcclient.h"
    2. #include
    3. #include
    4. IPCClient::IPCClient(int n)
    5. : _nID(n)
    6. , _bConnected(false)
    7. , _hPipe(INVALID_HANDLE_VALUE)
    8. {
    9. Connect();
    10. }
    11. IPCClient::~IPCClient()
    12. {
    13. if(_hPipe!=INVALID_HANDLE_VALUE){
    14. CloseHandle(_hPipe);
    15. _hPipe = INVALID_HANDLE_VALUE;
    16. }
    17. }
    18. bool IPCClient::Connect()
    19. {
    20. if(_bConnected)
    21. return _bConnected;
    22. _bConnected = false;
    23. std::string path = "\\\\.\\pipe\\pyfree";
    24. path += std::to_string(long long(_nID));
    25. if (!WaitNamedPipe(path.c_str(), NMPWAIT_USE_DEFAULT_WAIT/* NMPWAIT_WAIT_FOREVER*/) == FALSE)
    26. {
    27. _hPipe = CreateFile(path.c_str(),
    28. GENERIC_READ|GENERIC_WRITE,
    29. 0,
    30. NULL,
    31. OPEN_EXISTING,
    32. FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_OVERLAPPED*/,
    33. NULL);
    34. if(INVALID_HANDLE_VALUE != _hPipe)
    35. _bConnected = true;
    36. }
    37. return _bConnected;
    38. }
    39. int IPCClient::ReadInfo(char * buf, DWORD dwMaxLen, DWORD* pdwLen)
    40. {
    41. int nRet = 0;
    42. if(!Connect())
    43. return -1;
    44. if(!ReadFile(_hPipe,buf,dwMaxLen,pdwLen,NULL))
    45. {
    46. DWORD dwError = GetLastError();
    47. if(ERROR_IO_PENDING != dwError)
    48. {
    49. CloseHandle(_hPipe);
    50. _hPipe = INVALID_HANDLE_VALUE;
    51. _bConnected = false;
    52. nRet = 0 - dwError;
    53. }
    54. }
    55. return nRet;
    56. }
    57. int IPCClient::WriteInfo(char * buf, DWORD nMaxLen, DWORD* pdwLen)
    58. {
    59. int nRet = 0;
    60. if(!Connect())
    61. return -1;
    62. if(!WriteFile(_hPipe,buf,nMaxLen,pdwLen,NULL))
    63. {
    64. DWORD dwError = GetLastError();
    65. if(ERROR_IO_PENDING != dwError)
    66. {
    67. CloseHandle(_hPipe);
    68. _bConnected = false;
    69. _hPipe = INVALID_HANDLE_VALUE;
    70. nRet = 0 - dwError;
    71. }
    72. }
    73. return nRet;
    74. }

    ipcserver.h

    1. #ifndef _IPC_SERVER_H_
    2. #define _IPC_SERVER_H_
    3. #include
    4. //const DWORD BUFSIZE = 1024*64;
    5. const DWORD BUFSIZE = 512;
    6. const DWORD PIPE_TIMEOUT = 3000;
    7. class IPCServer
    8. {
    9. public:
    10. IPCServer(int n);
    11. ~IPCServer();
    12. int ReadInfo(char *, DWORD , DWORD*);
    13. int WriteInfo(char *, DWORD , DWORD*);
    14. private:
    15. bool Connect();
    16. bool DisConnect();
    17. private:
    18. int _nID;
    19. HANDLE _hPipe;
    20. bool _bConnected;
    21. };
    22. #endif // _IPC_SERVER_H_

    ipcserver.cpp实现管道创建、等待连接、数据读取等操作,管道名称和ipcclient保持一致,例如"\\\\.\\pipe\\pyfree"。

    1. #include "ipcserver.h"
    2. #include
    3. #include
    4. #include
    5. IPCServer::IPCServer(int n)
    6. : _nID(n)
    7. , _bConnected(false)
    8. , _hPipe(INVALID_HANDLE_VALUE)
    9. {
    10. Connect();
    11. }
    12. IPCServer::~IPCServer()
    13. {
    14. CloseHandle(_hPipe);
    15. }
    16. bool IPCServer::Connect()
    17. {
    18. if(_bConnected)
    19. return _bConnected;
    20. if(_hPipe == INVALID_HANDLE_VALUE)
    21. {
    22. std::string path = "\\\\.\\pipe\\pyfree";
    23. path += std::to_string(long long(_nID));
    24. _hPipe = CreateNamedPipe(path.c_str(),
    25. PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
    26. PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
    27. 1,
    28. BUFSIZE,
    29. BUFSIZE,
    30. PIPE_TIMEOUT,
    31. NULL);
    32. }
    33. if (_hPipe == INVALID_HANDLE_VALUE)
    34. {
    35. //std::cout << "CreatePipe Error" << std::endl;
    36. return _bConnected;
    37. }
    38. HANDLE hEvent;
    39. hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
    40. if (!hEvent)
    41. {
    42. CloseHandle(hEvent);
    43. //std::cout << "CreateEvent Error" << std::endl;
    44. return _bConnected;
    45. }
    46. OVERLAPPED olp;
    47. ZeroMemory(&olp,sizeof(OVERLAPPED));
    48. olp.hEvent=hEvent;
    49. if(!ConnectNamedPipe(_hPipe, &olp))
    50. {
    51. if(ERROR_IO_PENDING != GetLastError())//waitfor client link。
    52. {
    53. CloseHandle(_hPipe);
    54. CloseHandle(hEvent);
    55. _hPipe = INVALID_HANDLE_VALUE;
    56. //std::cout << "ConnectPipe Error" << std::endl;
    57. return _bConnected;
    58. }
    59. }
    60. DWORD waitforEvent = WaitForSingleObject(hEvent,INFINITE);
    61. if(WAIT_FAILED==waitforEvent||WAIT_TIMEOUT==waitforEvent)
    62. {
    63. CloseHandle(hEvent);
    64. CloseHandle(_hPipe);
    65. _hPipe = INVALID_HANDLE_VALUE;
    66. //std::cout << "ConnectPipe1 Error" << std::endl;
    67. return _bConnected;
    68. }
    69. CloseHandle(hEvent);
    70. _bConnected = true;
    71. return _bConnected;
    72. }
    73. bool IPCServer::DisConnect()
    74. {
    75. if(_bConnected)
    76. {
    77. if(DisconnectNamedPipe(_hPipe))
    78. {
    79. }
    80. CloseHandle(_hPipe);
    81. }
    82. _bConnected = false;
    83. _hPipe = INVALID_HANDLE_VALUE;
    84. return true;
    85. }
    86. int IPCServer::ReadInfo(char *wbuf, DWORD dwMaxLen, DWORD* pdwLen)
    87. {
    88. if(!Connect())
    89. return -1;
    90. int nRet = 0;
    91. if(!ReadFile(_hPipe,wbuf,dwMaxLen,pdwLen,NULL))
    92. {
    93. DWORD dwError = GetLastError();
    94. if(ERROR_IO_PENDING != dwError)
    95. {
    96. DisConnect();
    97. nRet = 0 - dwError;
    98. }
    99. }
    100. return nRet;
    101. }
    102. int IPCServer::WriteInfo(char *buf, DWORD dwMaxLen, DWORD* pdwLen)
    103. {
    104. int nRet = 0;
    105. if(!Connect())
    106. return -1;
    107. if(!WriteFile(_hPipe,buf,dwMaxLen,pdwLen,NULL))
    108. {
    109. DWORD dwError = GetLastError();
    110. if(ERROR_IO_PENDING != dwError)
    111. {
    112. DisConnect();
    113. nRet = 0 - dwError;
    114. }
    115. }
    116. return nRet;
    117. }

    main.cpp实现创建线程,调用管道客户端(ipcclient)、服务端(ipcserver)实现数据的逻辑发送和接收,可以通过调整线程数量、发送数据宽度等调节进行压力测试。

    1. // main.cpp
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "ipcclient.h"
    7. #include "ipcserver.h"
    8. #define _TotalFrame 100000 //帧数量
    9. #define _TotalThread 300 //线程数
    10. //#define _strWhith 1024*64 //发送信息长度
    11. #define _strWhith 512 //发送信息长度
    12. int nErrorCnt[_TotalThread] = {0};
    13. int nCount[_TotalThread]={0};
    14. int nAllSendCount[_TotalThread] = {0};
    15. int nAllReciveCount[_TotalThread] = {0};
    16. int m_MaxMsec[_TotalThread][2] = {0};
    17. int nSendCount[_TotalThread] ={0};
    18. unsigned __stdcall Sender( void* parg )
    19. {
    20. int n = (int ) parg; //线程编号
    21. char buf[_strWhith] = {0}; //发送信息及初始化
    22. IPCClient h(n);
    23. int msec=0; //开始标记
    24. for(int i=0;i<_TotalFrame;)
    25. {
    26. nAllSendCount[n]++;
    27. int *p = (int *)buf;
    28. p[0] = n; //线程编号加入发送信息
    29. p[1] = i; //发送次数加入发送信息
    30. buf[_strWhith-1] = 'N';
    31. DWORD wlen=0; //实际发送长度标记
    32. DWORD dwBegin = GetTickCount();
    33. int ret = h.WriteInfo(buf, _strWhith/4, &wlen); //发送四分之一长度数据
    34. msec = GetTickCount() - dwBegin;
    35. if(msec > m_MaxMsec[n][0]){
    36. m_MaxMsec[n][0] = msec;
    37. m_MaxMsec[n][1] = ret;
    38. }
    39. if(3==ret){
    40. std::cout << "error: info too long!" << std::endl;
    41. }
    42. if( ret == 0&&_strWhith/4==wlen)
    43. {
    44. i++;
    45. nCount[n] = i;
    46. }
    47. ::Sleep(1);
    48. }
    49. return 1;
    50. }
    51. unsigned __stdcall Receiver( void* parg )
    52. {
    53. int n = (int ) parg; //线程编号
    54. char buf[_strWhith] = {0}; //接收信息及初始化
    55. IPCServer h(n);
    56. int msec = 0;
    57. int want = 0;
    58. for(int i=0;i<_TotalFrame;)
    59. {
    60. nAllReciveCount[n]++;
    61. int *p = (int *) buf;
    62. int nRet = 0;
    63. DWORD rlen = 0;
    64. DWORD dwBegin = GetTickCount();
    65. nRet = h.ReadInfo(buf, _strWhith,&rlen);
    66. msec = GetTickCount() - dwBegin;
    67. if(msec > m_MaxMsec[n][0]){
    68. m_MaxMsec[n][0] = msec;
    69. m_MaxMsec[n][1] = nRet;
    70. }
    71. //实际接收数据长度不是四分之一,说明缓存过多,对管道的数据读取效率到了极限
    72. if(nRet == 0&&_strWhith/4!=rlen){
    73. if(n<10)
    74. std::cout << "Thread " << n << " received " << rlen << " string , send order:" << p[1] << std::endl;
    75. int a=0;
    76. if(_strWhith/2==rlen)
    77. {
    78. a=2;
    79. }
    80. else if(3*_strWhith/4==rlen)
    81. {
    82. a=3;
    83. }
    84. else if(_strWhith==rlen)
    85. {
    86. a=4;
    87. }
    88. if(p[1] != want)
    89. {
    90. if(n<10)
    91. std::cout << "thread " << n << " want " << want << " , actual:" << p[1] << std::endl;
    92. nErrorCnt[n] = nErrorCnt[n] + 2;
    93. }
    94. nCount[n] = nCount[n] + a;
    95. want = p[1] + a;
    96. i=i+a;
    97. }
    98. //实际接收数据长度就是四分之一,即每次发送都能及时完全读取
    99. if(nRet == 0&&_strWhith/4==rlen)
    100. {
    101. if(p[1] != want)
    102. {
    103. if(n<1)
    104. std::cout << "Thread " << n << " want " << want << " , actual:" << p[1] << std::endl;
    105. nErrorCnt[n] ++;
    106. }
    107. nCount[n] ++;
    108. want = p[1] + 1;
    109. i++;
    110. }
    111. ::Sleep(1);
    112. }
    113. return 1;
    114. }
    115. int _tmain(int argc, _TCHAR* argv[])
    116. {
    117. unsigned nThreadID[2][_TotalThread]; //两种线程句柄,一组用于发送、一组用于接收
    118. int bSender = 0;
    119. std::cout << "0: Receiver, 1: Sender" << std::endl;
    120. int ch = _getch(); //本次启动用于发送或接收选择
    121. if(ch == '1')
    122. {
    123. bSender = 1;
    124. }
    125. std::cout <<(bSender?"Start Sending":"Start Receiving") << std::endl;
    126. for(int i=0;i<_TotalThread;i++)
    127. {
    128. HANDLE hThread;
    129. if(bSender)
    130. hThread = (HANDLE)_beginthreadex(NULL, 0 , Sender, (void *)i, 0, nThreadID[0] + i);
    131. else
    132. hThread = (HANDLE)_beginthreadex(NULL, 0 , Receiver, (void *)i, 0, nThreadID[1] + i);
    133. if( 0 == hThread ){
    134. std::cout << "create thread : " <<(bSender?nThreadID[0][i]:nThreadID[1][i])<< " error! " << std::endl;
    135. }
    136. }
    137. bool bExit = false;
    138. for(;!bExit;)
    139. {
    140. ::Sleep(1);
    141. if(_kbhit())
    142. {
    143. int ch = _getch();
    144. switch(ch)
    145. {
    146. case 'q':
    147. bExit = true;
    148. break;
    149. case 'd':
    150. std::cout << " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " << std::endl;
    151. for(int i=0;i<_TotalThread;i++){
    152. //if(m_MaxMsec[i][0]>20 || nErrorCnt[i])
    153. {
    154. std::cout << (bSender?"Sender ":"Reciever ")
    155. << i << /*" ,Max is:" << nMaxmsec <<*/" Error: "
    156. << nErrorCnt[i] << " Success : "<
    157. << (bSender?" STotal: ":" RTotal: ") << (bSender?nAllSendCount[i]:nAllReciveCount[i])
    158. << " maxTime: "<< m_MaxMsec[i][0]
    159. << " type: " << m_MaxMsec[i][1]
    160. << std::endl;
    161. }
    162. }
    163. break;
    164. }
    165. }
    166. }
    167. return 0;
    168. }

    三、编译实现

            CMakeLists.txt内容,本文给出Debug版本的。

    1. # CMake 最低版本号要求
    2. cmake_minimum_required(VERSION 2.8)
    3. # 项目信息
    4. project(ipc_test)
    5. #
    6. message(STATUS "windows compiling...")
    7. add_definitions(-D_PLATFORM_IS_WINDOWS_)
    8. #set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
    9. set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
    10. set(WIN_OS true)
    11. #
    12. set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
    13. # 指定源文件的目录,并将名称保存到变量
    14. SET(source_h
    15. #
    16. ${PROJECT_SOURCE_DIR}/ipc/ipcclient.h
    17. ${PROJECT_SOURCE_DIR}/ipc/ipcserver.h
    18. )
    19. SET(source_cpp
    20. #
    21. ${PROJECT_SOURCE_DIR}/ipc/ipcclient.cpp
    22. ${PROJECT_SOURCE_DIR}/ipc/ipcserver.cpp
    23. ${PROJECT_SOURCE_DIR}/src/main.cpp
    24. )
    25. #头文件目录
    26. include_directories(${PROJECT_SOURCE_DIR}/ipc)
    27. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/bin)
    28. # 指定生成目标
    29. add_executable(ipc_testd ${source_h} ${source_cpp})

    打开vs2010 command prompt命令工具

    1. cmake -G "Visual Studio 10 2010 Win64" ..
    2. msbuild ipc_test.sln /p:Platform="x64"

    编译过程如下:

    1. D:\workForMy\workspace\ipc_test\build>cmake -G "Visual Studio 10 2010 Win64" ..
    2. -- The C compiler identification is MSVC 16.0.40219.1
    3. -- The CXX compiler identification is MSVC 16.0.40219.1
    4. -- Check for working C compiler: d:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin/x86_amd64/cl.exe
    5. -- Check for working C compiler: d:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin/x86_amd64/cl.exe -- works
    6. -- Detecting C compiler ABI info
    7. -- Detecting C compiler ABI info - done
    8. -- Check for working CXX compiler: d:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin/x86_amd64/cl.exe
    9. -- Check for working CXX compiler: d:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin/x86_amd64/cl.exe -- works
    10. -- Detecting CXX compiler ABI info
    11. -- Detecting CXX compiler ABI info - done
    12. -- Detecting CXX compile features
    13. -- Detecting CXX compile features - done
    14. -- windows compiling...
    15. -- Configuring done
    16. -- Generating done
    17. -- Build files have been written to: D:/workForMy/workspace/ipc_test/build
    18. D:\workForMy\workspace\ipc_test\build>msbuild ipc_test.sln /p:Platform="x64"
    19. Microsoft(R) 生成引擎版本 4.8.4084.0
    20. [Microsoft .NET Framework 版本 4.0.30319.42000]
    21. 版权所有 (C) Microsoft Corporation。保留所有权利。
    22. 在此解决方案中一次生成一个项目。若要启用并行生成,请添加“/m”开关。
    23. 生成启动时间为 2022/9/11 15:34:14
    24. 节点 1 上的项目“D:\workForMy\workspace\ipc_test\build\ipc_test.sln”(默认目标)。
    25. ValidateSolutionConfiguration:
    26. 正在生成解决方案配置“Debug|x64”。
    27. ValidateProjects:
    28. 在解决方案配置“Debug|x64”中未选定生成项目“ALL_BUILD”。
    29. 项目“D:\workForMy\workspace\ipc_test\build\ipc_test.sln”(1)正在节点 1 上生成“D:\workForMy\workspace\ipc_test\build\ZERO_CHECK.vc
    30. xproj”(2) (默认目标)。
    31. PrepareForBuild:
    32. 正在创建目录“x64\Debug\ZERO_CHECK\”。
    33. InitializeBuildStatus:
    34. 正在创建“x64\Debug\ZERO_CHECK\ZERO_CHECK.unsuccessfulbuild”,因为已指定“AlwaysCreate”。
    35. CustomBuild:
    36. Checking Build System
    37. CMake does not need to re-run because D:/workForMy/workspace/ipc_test/build/CMakeFiles/generate.stamp is up-to-date.
    38. FinalizeBuildStatus:
    39. 正在删除文件“x64\Debug\ZERO_CHECK\ZERO_CHECK.unsuccessfulbuild”。
    40. 正在对“x64\Debug\ZERO_CHECK\ZERO_CHECK.lastbuildstate”执行 Touch 任务。
    41. 已完成生成项目“D:\workForMy\workspace\ipc_test\build\ZERO_CHECK.vcxproj”(默认目标)的操作。
    42. 项目“D:\workForMy\workspace\ipc_test\build\ipc_test.sln”(1)正在节点 1 上生成“D:\workForMy\workspace\ipc_test\build\ipc_testd.vcx
    43. proj.metaproj”(3) (默认目标)。
    44. 项目“D:\workForMy\workspace\ipc_test\build\ipc_testd.vcxproj.metaproj”(3)正在节点 1 上生成“D:\workForMy\workspace\ipc_test\build
    45. \ipc_testd.vcxproj”(4) (默认目标)。
    46. PrepareForBuild:
    47. 正在创建目录“ipc_testd.dir\Debug\”。
    48. InitializeBuildStatus:
    49. 正在创建“ipc_testd.dir\Debug\ipc_testd.unsuccessfulbuild”,因为已指定“AlwaysCreate”。
    50. CustomBuild:
    51. Building Custom Rule D:/workForMy/workspace/ipc_test/CMakeLists.txt
    52. CMake does not need to re-run because D:/workForMy/workspace/ipc_test/build/CMakeFiles/generate.stamp is up-to-date.
    53. MakeDirsForCl:
    54. 正在创建目录“D:\workForMy\workspace\ipc_test\build\Debug”。
    55. ClCompile:
    56. d:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\x86_amd64\CL.exe /c /ID:\workForMy\workspace\ipc_test\ipc
    57. /I"D:\workForSoftware\Visual Leak Detector\include" /Zi /nologo /W3 /WX- /Od /Ob0 /D WIN32 /D _WINDOWS /D _PLATFORM_I
    58. S_WINDOWS_ /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /F
    59. o"ipc_testd.dir\Debug\\" /Fd"ipc_testd.dir\Debug\vc100.pdb" /Gd /TP /errorReport:queue ..\ipc\ipcclient.cpp ..\ipc\ip
    60. cserver.cpp ..\src\main.cpp
    61. ipcclient.cpp
    62. ipcserver.cpp
    63. main.cpp
    64. Generating Code...
    65. ManifestResourceCompile:
    66. C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\rc.exe /nologo /fo"ipc_testd.dir\Debug\ipc_testd.exe.embed.ma
    67. nifest.res" ipc_testd.dir\Debug\ipc_testd_manifest.rc
    68. Link:
    69. d:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\x86_amd64\link.exe /ERRORREPORT:QUEUE /OUT:"D:\workForMy\w
    70. orkspace\ipc_test\bin\ipc_testd.exe" /INCREMENTAL /NOLOGO /LIBPATH:"D:\workForSoftware\Visual Leak Detector\lib\Win64
    71. " kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.li
    72. b /MANIFEST /ManifestFile:"ipc_testd.dir\Debug\ipc_testd.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' u
    73. iAccess='false'" /DEBUG /PDB:"D:/workForMy/workspace/ipc_test/bin/ipc_testd.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMIC
    74. BASE /NXCOMPAT /IMPLIB:"D:/workForMy/workspace/ipc_test/bin/Debug/ipc_testd.lib" /MACHINE:X64 ipc_testd.dir\Debug\ipc
    75. _testd.exe.embed.manifest.res
    76. ipc_testd.dir\Debug\ipcclient.obj
    77. ipc_testd.dir\Debug\ipcserver.obj
    78. ipc_testd.dir\Debug\main.obj /machine:x64
    79. ipc_testd.vcxproj -> D:\workForMy\workspace\ipc_test\bin\ipc_testd.exe
    80. Manifest:
    81. C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /out:"ipc_testd.dir\Debug\ipc_testd.e
    82. xe.embed.manifest" /manifest ipc_testd.dir\Debug\ipc_testd.exe.intermediate.manifest
    83. C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\rc.exe /nologo /fo"ipc_testd.dir\Debug\ipc_testd.exe.embed.ma
    84. nifest.res" ipc_testd.dir\Debug\ipc_testd_manifest.rc
    85. LinkEmbedManifest:
    86. d:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\x86_amd64\link.exe /ERRORREPORT:QUEUE /OUT:"D:\workForMy\w
    87. orkspace\ipc_test\bin\ipc_testd.exe" /INCREMENTAL /NOLOGO /LIBPATH:"D:\workForSoftware\Visual Leak Detector\lib\Win64
    88. " kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.li
    89. b /MANIFEST /ManifestFile:"ipc_testd.dir\Debug\ipc_testd.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' u
    90. iAccess='false'" /DEBUG /PDB:"D:/workForMy/workspace/ipc_test/bin/ipc_testd.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMIC
    91. BASE /NXCOMPAT /IMPLIB:"D:/workForMy/workspace/ipc_test/bin/Debug/ipc_testd.lib" /MACHINE:X64 ipc_testd.dir\Debug\ipc
    92. _testd.exe.embed.manifest.res
    93. ipc_testd.dir\Debug\ipcclient.obj
    94. ipc_testd.dir\Debug\ipcserver.obj
    95. ipc_testd.dir\Debug\main.obj /machine:x64
    96. ipc_testd.vcxproj -> D:\workForMy\workspace\ipc_test\bin\ipc_testd.exe
    97. FinalizeBuildStatus:
    98. 正在删除文件“ipc_testd.dir\Debug\ipc_testd.unsuccessfulbuild”。
    99. 正在对“ipc_testd.dir\Debug\ipc_testd.lastbuildstate”执行 Touch 任务。
    100. 已完成生成项目“D:\workForMy\workspace\ipc_test\build\ipc_testd.vcxproj”(默认目标)的操作。
    101. 已完成生成项目“D:\workForMy\workspace\ipc_test\build\ipc_testd.vcxproj.metaproj”(默认目标)的操作。
    102. 已完成生成项目“D:\workForMy\workspace\ipc_test\build\ipc_test.sln”(默认目标)的操作。
    103. 已成功生成。
    104. 0 个警告
    105. 0 个错误
    106. 已用时间 00:00:02.99
    107. D:\workForMy\workspace\ipc_test\build>

    启动测试:

     本文测试了多次,程序启动后大概执行近2分钟后,按“d”输出打印结果,最终是所有线程、所有数据的写入及读取逻辑顺序都是正确的

    四、补充

    应部分读者要求,完整代码已经上传CSDN:

    win下命名管道通信压力测试实现的完整c++示例代码-C++文档类资源-CSDN下载

  • 相关阅读:
    ROS2入门之基本介绍
    AppCube视角浅析: 艾瑞咨询《2022年中国低代码行业研究报告》
    探索Python中的装饰器
    前端进击笔记第二十一节 如何搭建前端监控体系为业务排忧解难?
    旁边的同事突然晋升阿里P7,只因偷偷学习了这份JVM笔记?
    笔试强训48天——day16
    C# 图解教程 第5版 —— 第5章 类的基本概念
    基于粒子群优化算法的微型燃气轮机冷热电联供系统优化调度(Matlab代码实现)
    流程控制.
    螺杆支撑座大作用
  • 原文地址:https://blog.csdn.net/py8105/article/details/126805147