Windows系統編程之進程間通信

Windows系統編程之進程間通信
作者:北極星2003
來源:看雪論壇(www.pediy.com)
Windows?的IPC(進程間通信)機制主要是異步管道和命名管道。(至于其他的IPC方式,例如內存映射、郵槽等這里就不介紹了)
管道(pipe)是用于進程間通信的共享內存區域。創建管道的進程稱為管道服務器,而連接到這個管道的進程稱為管道客戶端。一個進程向管道寫入信息,而另外一個進程從管道讀取信息。
異步管道是基于字符和半雙工的(即單向),一般用于程序輸入輸出的重定向;命名管道則強大地多,它們是面向消息和全雙工的,同時還允許網絡通信,用于創建客戶端/服務器系統。
一、異步管道(實現比較簡單,直接通過實例來講解)
實驗目標:當前有sample.cpp,?sample.exe,?sample.in這三個文件,sample.exe為sample.cpp的執行程序,sample.cpp只是一個簡單的程序示例(簡單求和),如下:

代碼:
[cpp]?view plain?copy
  1. #include?<iostream.h>??
  2. int?main()??
  3. {??
  4. ??int?a,?b?;??
  5. ??while?(?cin?>>?a?>>?b?&&?(?a?||?b?)?)??
  6. ????cout?<<?a?+?b?<<?endl?;??
  7. ??return?0;??
  8. }??
Sample.in文件是輸入文件,內容:
32?433
542?657
0?0
要求根據sample.exe和它的輸入數據,把輸出數據重定向到sample.out
流程分析:實際這個實驗中包含兩個部分,把輸入數據重定向到sample.exe?和把輸出數據重定向到sample.out。在命令行下可以很簡單的實現這個功能“sample?<sample.in?>sample.out”,這個命令也是利用管道特性實現的,現在我們就根據異步管道的實現原理自己來實現這個功能。
管道是基于半雙工(單向)的,這里有兩個重定向的過程,顯然需要創建兩個管道,下面給出流程圖:
異步管道實現的流程圖說明:
1)。父進程是我們需要實現的,其中需要創建管道A,管道B,和子進程,整個實現流程分為4個操作。
2)。管道A:輸入管道
3)。管道B:輸出管道
4)。操作A:把輸入文件sample.in的數據寫入輸入管道(管道A)
5)。操作B:子進程從輸入管道中讀取數據,作為該進程的加工原料。通常,程序的輸入數據由標準的輸入設備輸入,這里實現輸入重定向,即把輸入管道作為輸入設備。
6)。操作C:子進程把加工后的成品(輸出數據)輸出到輸出管道。通常,程序的輸出數據會輸出到標準的輸出設備,一般為屏幕,這里實現輸出重定向,即把輸出管道作為輸出設備。
7)。操作D:把輸出管道的數據寫入輸出文件
需要注意的是,管道的本質只是一個共享的內存區域。這個實驗中,管道區域處于父進程的地址空間中,父進程的作用是提供環境和資源,并協調子進程進行加工。
程序源碼:
代碼:
[cpp]?view plain?copy
  1. #include?<windows.h>???
  2. #include?<iostream.h>??
  3. ??
  4. const?int?BUFSIZE?=?4096?;???
  5. HANDLE??hChildStdinRd,?hChildStdinWr,?hChildStdinWrDup,???
  6. ???????hChildStdoutRd,hChildStdoutWr,hChildStdoutRdDup,???
  7. ????hSaveStdin,????hSaveStdout;???
  8. ??
  9. BOOL?CreateChildProcess(LPTSTR);???
  10. VOID?WriteToPipe(LPTSTR);???
  11. VOID?ReadFromPipe(LPTSTR);???
  12. VOID?ErrorExit(LPTSTR);???
  13. VOID?ErrMsg(LPTSTR,?BOOL);???
  14. void?main(?int?argc,?char?*argv[]?)???
  15. {????
  16. ??//?處理輸入參數??
  17. ??if?(?argc?!=?4?)??
  18. ????return?;??
  19. ??
  20. ??//?分別用來保存命令行,輸入文件名(CPP/C),輸出文件名(保存編譯信息)??
  21. ??LPTSTR?lpProgram?=?new?char[?strlen(argv[1])?]?;??
  22. ??strcpy?(?lpProgram,?argv[1]?)?;??
  23. ??LPTSTR?lpInputFile?=?new?char[?strlen(argv[2])?];??
  24. ??strcpy?(?lpInputFile,?argv[2]?)?;??
  25. ??LPTSTR?lpOutputFile?=?new?char[?strlen(argv[3])?]?;??
  26. ??strcpy?(?lpOutputFile,?argv[3]?)?;??????
  27. ????
  28. ??SECURITY_ATTRIBUTES?saAttr;???
  29. ??saAttr.nLength?=?sizeof(SECURITY_ATTRIBUTES);???
  30. ??saAttr.bInheritHandle?=?TRUE;???
  31. ??saAttr.lpSecurityDescriptor?=?NULL;???
  32. ?????
  33. ??/************************************************?
  34. ???*????redirecting?child?process's?STDOUT??*?
  35. ???************************************************/??
  36. ??hSaveStdout?=?GetStdHandle(STD_OUTPUT_HANDLE);???
  37. ????
  38. ??if?(!?CreatePipe(&hChildStdoutRd,?&hChildStdoutWr,?&saAttr,?0))???
  39. ????ErrorExit("Stdout?pipe?creation?failed/n");???
  40. ??????
  41. ??if?(!?SetStdHandle(STD_OUTPUT_HANDLE,?hChildStdoutWr))???
  42. ????ErrorExit("Redirecting?STDOUT?failed");???
  43. ????
  44. ??BOOL?fSuccess?=?DuplicateHandle(??
  45. ????GetCurrentProcess(),???
  46. ????hChildStdoutRd,??
  47. ????????GetCurrentProcess(),???
  48. ????&hChildStdoutRdDup?,??
  49. ????0,??
  50. ????????FALSE,??
  51. ????????DUPLICATE_SAME_ACCESS);??
  52. ????if(?!fSuccess?)??
  53. ????????ErrorExit("DuplicateHandle?failed");??
  54. ????CloseHandle(hChildStdoutRd);??
  55. ????
  56. ??/************************************************?
  57. ???*????redirecting?child?process's?STDIN????*?
  58. ???************************************************/??
  59. ??hSaveStdin?=?GetStdHandle(STD_INPUT_HANDLE);???
  60. ??
  61. ??if?(!?CreatePipe(&hChildStdinRd,?&hChildStdinWr,?&saAttr,?0))???
  62. ????ErrorExit("Stdin?pipe?creation?failed/n");???
  63. ????
  64. ??if?(!?SetStdHandle(STD_INPUT_HANDLE,?hChildStdinRd))???
  65. ????ErrorExit("Redirecting?Stdin?failed");???
  66. ????
  67. ??fSuccess?=?DuplicateHandle(??
  68. ????GetCurrentProcess(),???
  69. ????hChildStdinWr,???
  70. ????GetCurrentProcess(),??
  71. ????&hChildStdinWrDup,???
  72. ????0,???
  73. ????FALSE,???????????????????
  74. ????DUPLICATE_SAME_ACCESS);???
  75. ??if?(!?fSuccess)???
  76. ????ErrorExit("DuplicateHandle?failed");???
  77. ??CloseHandle(hChildStdinWr);?????
  78. ??
  79. ??/************************************************?
  80. ???*??????創建子進程(即啟動SAMPLE.EXE)????*?
  81. ???************************************************/??
  82. ??fSuccess?=?CreateChildProcess(?lpProgram?);??
  83. ??if?(?!fSuccess?)???
  84. ????ErrorExit("Create?process?failed");???
  85. ????
  86. ??//?父進程輸入輸出流的還原設置??
  87. ??if?(!?SetStdHandle(STD_INPUT_HANDLE,?hSaveStdin))???
  88. ????ErrorExit("Re-redirecting?Stdin?failed/n");???
  89. ??if?(!?SetStdHandle(STD_OUTPUT_HANDLE,?hSaveStdout))???
  90. ????ErrorExit("Re-redirecting?Stdout?failed/n");???
  91. ??
  92. ??WriteToPipe(?lpInputFile?)?;??
  93. ??ReadFromPipe(?lpOutputFile?);???
  94. ??????????delete?lpProgram?;??
  95. ??????????delete?lpInputFile?;??
  96. ??????????delete?lpOutputFile?;??
  97. }???
  98. ??
  99. BOOL?CreateChildProcess(?LPTSTR?lpProgram?)???
  100. {???
  101. ??PROCESS_INFORMATION?piProcInfo;???
  102. ??STARTUPINFO?siStartInfo;??
  103. ??BOOL?bFuncRetn?=?FALSE;???
  104. ????
  105. ??ZeroMemory(?&piProcInfo,?sizeof(PROCESS_INFORMATION)?);??
  106. ??ZeroMemory(?&siStartInfo,?sizeof(STARTUPINFO)?);??
  107. ??siStartInfo.cb?=?sizeof(STARTUPINFO);???
  108. ????
  109. ??bFuncRetn?=?CreateProcess?(?NULL,?lpProgram,?NULL,?NULL,?TRUE,?/??
  110. ????????????????0,?NULL,?NULL,?&siStartInfo,?&piProcInfo);??
  111. ??if?(bFuncRetn?==?0)???
  112. ??{??
  113. ????ErrorExit("CreateProcess?failed/n");??
  114. ????return?0;??
  115. ??}???
  116. ??else???
  117. ??{??
  118. ????CloseHandle(piProcInfo.hProcess);??
  119. ????CloseHandle(piProcInfo.hThread);??
  120. ????return?bFuncRetn;??
  121. ??}??
  122. }??
  123. ??
  124. VOID?WriteToPipe(?LPTSTR?lpInputFile?)???
  125. {???
  126. ??HANDLE?hInputFile?=?CreateFile(lpInputFile,?GENERIC_READ,?0,?NULL,???
  127. ????OPEN_EXISTING,?FILE_ATTRIBUTE_READONLY,?NULL);???
  128. ??if?(hInputFile?==?INVALID_HANDLE_VALUE)???
  129. ????return?;??
  130. ??
  131. ??BOOL?fSuccess?;??
  132. ??DWORD?dwRead,?dwWritten;???
  133. ??CHAR?chBuf[BUFSIZE]?=?{0}?;???
  134. ????
  135. ??for?(;;)???
  136. ??{???
  137. ????fSuccess?=?ReadFile(?hInputFile,?chBuf,?BUFSIZE,?&dwRead,?NULL)?;??
  138. ????if?(?!fSuccess?||?dwRead?==?0)??
  139. ??????break;???
  140. ??
  141. ????fSuccess?=?WriteFile(?hChildStdinWrDup,?chBuf,?dwRead,?&dwWritten,?NULL)?;??
  142. ????if?(?!fSuccess?)???
  143. ??????break;???
  144. ??}???
  145. ??????
  146. ??if?(!?CloseHandle(hChildStdinWrDup))???
  147. ????ErrorExit("Close?pipe?failed/n");???
  148. ??
  149. ??CloseHandle?(?hInputFile?)?;??
  150. }???
  151. ??
  152. VOID?ReadFromPipe(?LPTSTR?lpOutputFile?)???
  153. {???
  154. ??HANDLE?hOutputFile?=?CreateFile(?lpOutputFile,?GENERIC_READ|GENERIC_WRITE,???
  155. ????FILE_SHARE_WRITE,?NULL,?CREATE_ALWAYS,?FILE_ATTRIBUTE_NORMAL,?NULL);???
  156. ??if?(hOutputFile?==?INVALID_HANDLE_VALUE)???
  157. ????return?;??
  158. ??
  159. ??BOOL?fSuccess?;??
  160. ??DWORD?dwRead,?dwWritten;???
  161. ??CHAR?chBuf[BUFSIZE]?=?{?0?};???
  162. ????
  163. ??if?(!CloseHandle(hChildStdoutWr))???
  164. ????ErrorExit("Closing?handle?failed");???
  165. ????
  166. ??for?(;;)???
  167. ??{???
  168. ????fSuccess?=?ReadFile(?hChildStdoutRdDup,?chBuf,?BUFSIZE,?&dwRead,?NULL)?;??
  169. ????if(?!fSuccess?||?dwRead?==?0)???
  170. ????{??
  171. ??????break;???
  172. ????}??
  173. ????fSuccess?=?WriteFile(?hOutputFile,?chBuf,?dwRead,?&dwWritten,?NULL)?;??
  174. ????if?(?!fSuccess?)???
  175. ??????break;???
  176. ??}???
  177. ??
  178. ??CloseHandle?(?hOutputFile?)?;??
  179. }???
  180. VOID?ErrorExit?(LPTSTR?lpszMessage)???
  181. {???
  182. ??MessageBox(?0,?lpszMessage,?0,?0?);???
  183. }??
二、命名管道
命名管道具有以下幾個特征:
(1)命名管道是雙向的,所以兩個進程可以通過同一管道進行交互。
(2)命名管道不但可以面向字節流,還可以面向消息,所以讀取進程可以讀取寫進程發送的不同長度的消息。
(3)多個獨立的管道實例可以用一個名稱來命名。例如幾個客戶端可以使用名稱相同的管道與同一個服務器進行并發通信。
(4)命名管道可以用于網絡間兩個進程的通信,而其實現的過程與本地進程通信完全一致。
實驗目標:在客戶端輸入數據a和b,然后發送到服務器并計算a+b,然后把計算結果發送到客戶端。可以多個客戶端與同一個服務器并行通信。
界面設計:
難點所在:
實現的過程比較簡單,但有一個難點。原本當服務端使用ConnectNamedPipe函數后,如果有客戶端連接,就可以直接進行交互。原來我在實現過程中,當管道空閑時,管道的線程函數會無限(INFINITE)阻塞。若現在需要停止服務,就必須結束所有的線程,TernimateThread可以作為一個結束線程的方法,但我基本不用這個函數。一旦使用這個函數之后,目標線程就會立即結束,但如果此時的目標線程正在操作互斥資源、內核調用、或者是操作共享DLL的全局變量,可能會出現互斥資源無法釋放、內核異常等現象。這里我用重疊I/0來解決這個問題,在創建PIPE時使用FILE_FLAG_OVERLAPPED標志,這樣使用ConnectNamedPipe后會立即返回,但線程的阻塞由等待函數WaitForSingleObject來實現,等待OVERLAPPED結構的事件對象被設置。
客戶端主要代碼:
代碼:
[cpp]?view plain?copy
  1. void?CMyDlg::OnSubmit()???
  2. {??
  3. ??//?打開管道??
  4. ??HANDLE?hPipe?=?CreateFile(".//Pipe//NamedPipe",?GENERIC_READ?|?GENERIC_WRITE,?/??
  5. ????0,?NULL,?OPEN_EXISTING,?FILE_ATTRIBUTE_NORMAL,?NULL)?;??
  6. ??if?(?hPipe?==?INVALID_HANDLE_VALUE?)??
  7. ??{??
  8. ????this->MessageBox?(?"打開管道失敗,服務器尚未啟動,或者客戶端數量過多"?)?;??
  9. ????return?;??
  10. ??}??
  11. ??
  12. ??DWORD?nReadByte,?nWriteByte?;??
  13. ??char?szBuf[1024]?=?{0}?;??
  14. ??//?把兩個整數(a,b)格式化為字符串??
  15. ??sprintf?(?szBuf,?"%d?%d",?this->nFirst,?this->nSecond?)?;??
  16. ??//?把數據寫入管道??
  17. ??WriteFile?(?hPipe,?szBuf,?strlen(szBuf),?&nWriteByte,?NULL?)?;??
  18. ??
  19. ??memset?(?szBuf,?0,?sizeof(szBuf)?)?;??
  20. ??//?讀取服務器的反饋信息??
  21. ??ReadFile?(?hPipe,?szBuf,?1024,?&nReadByte,?NULL?)?;??
  22. ??//?把返回信息格式化為整數??
  23. ??sscanf?(?szBuf,?"%d",?&(this->nResValue)?)?;??
  24. ??this->UpdateData?(?false?)?;??
  25. ??CloseHandle?(?hPipe?)?;??
  26. }??
服務端主要代碼:
代碼:
[cpp]?view plain?copy
  1. //?啟動服務??
  2. void?CMyDlg::OnStart()???
  3. {??
  4. ??CString?lpPipeName?=?".//Pipe//NamedPipe"?;??
  5. ??for?(?UINT?i?=?0;?i?<?nMaxConn;?i++?)??
  6. ??{??
  7. ????//?創建管道實例??
  8. ????PipeInst[i].hPipe?=??CreateNamedPipe?(?lpPipeName,?PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,?/??
  9. ??????????PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT,?nMaxConn,?0,?0,?1000,?NULL?)?;??
  10. ????if?(?PipeInst[i].hPipe?==?INVALID_HANDLE_VALUE?)??
  11. ????{??
  12. ??????DWORD?dwErrorCode?=?GetLastError?()?;??
  13. ??????this->MessageBox?(?"創建管道錯誤!"?)?;??
  14. ??????return?;??
  15. ????}??
  16. ????//?為每個管道實例創建一個事件對象,用于實現重疊IO??
  17. ????PipeInst[i].hEvent??=??CreateEvent?(?NULL,?false,?false,?false?)?;??
  18. ????//?為每個管道實例分配一個線程,用于響應客戶端的請求??
  19. ????PipeInst[i].hTread?=?AfxBeginThread?(?ServerThread,?&PipeInst[i],?THREAD_PRIORITY_NORMAL?)?;??
  20. ??}??
  21. ????
  22. ??this->SetWindowText?(?"命名管道實例之服務器(運行)"?)?;??
  23. ??this->MessageBox?(?"服務啟動成功"?)?;??
  24. }??
  25. //?停止服務??
  26. void?CMyDlg::OnStop()???
  27. {??
  28. ??DWORD?dwNewMode?=?PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_NOWAIT?;??
  29. ??for?(?UINT?i?=?0;?i?<?nMaxConn;?i++?)??
  30. ??{??
  31. ????SetEvent?(?PipeInst[i].hEvent?)?;??
  32. ????CloseHandle?(?PipeInst[i].hTread?)?;??
  33. ????CloseHandle?(?PipeInst[i].hPipe?)?;??
  34. ??}??
  35. ??????
  36. ??this->SetWindowText?(?"命名管道實例之服務器"?)?;??
  37. ??this->MessageBox?(?"停止啟動成功"?)?;??
  38. }??
  39. ??
  40. //?線程服務函數??
  41. UINT?ServerThread?(?LPVOID?lpParameter?)??
  42. {??
  43. ??DWORD??nReadByte?=?0,?nWriteByte?=?0,?dwByte?=?0?;????
  44. ??char??szBuf[MAX_BUFFER_SIZE]?=?{0}?;??
  45. ??PIPE_INSTRUCT??CurPipeInst?=?*(PIPE_INSTRUCT*)lpParameter?;??
  46. ??OVERLAPPED?OverLapStruct?=?{?0,?0,?0,?0,?CurPipeInst.hEvent?}?;??
  47. ??while?(?true?)??
  48. ??{??
  49. ????memset?(?szBuf,?0,?sizeof(szBuf)?)?;????
  50. ????//?命名管道的連接函數,等待客戶端的連接(只針對NT)??
  51. ????ConnectNamedPipe?(?CurPipeInst.hPipe,?&OverLapStruct?)?;??
  52. ????//?實現重疊I/0,等待OVERLAPPED結構的事件對象??
  53. ????WaitForSingleObject?(?CurPipeInst.hEvent,?INFINITE?)?;??
  54. ????//?檢測I/0是否已經完成,如果未完成,意味著該事件對象是人工設置,即服務需要停止??
  55. ????if?(?!GetOverlappedResult?(?CurPipeInst.hPipe,?&OverLapStruct,?&dwByte,?true?)?)??
  56. ??????break?;??
  57. ??
  58. ????//?從管道中讀取客戶端的請求信息??
  59. ????if?(?!ReadFile?(?CurPipeInst.hPipe,?szBuf,?MAX_BUFFER_SIZE,?&nReadByte,?NULL?)?)??
  60. ????{??
  61. ??????MessageBox?(?0,?"讀取管道錯誤!",?0,?0?)?;??
  62. ??????break?;??
  63. ????}??
  64. ??????
  65. ????int?a,?b?;??
  66. ????sscanf?(?szBuf,?"%d?%d",?&a,?&b?)?;??
  67. ????pMyDlg->nFirst????=?a?;??
  68. ????pMyDlg->nSecond????=?b?;??
  69. ????pMyDlg->nResValue??=?a?+?b?;??
  70. ????memset?(?szBuf,?0,?sizeof(szBuf)?)?;??
  71. ????sprintf?(?szBuf,?"%d",?pMyDlg->nResValue?)?;??
  72. ????//?把反饋信息寫入管道??
  73. ????WriteFile?(?CurPipeInst.hPipe,?szBuf,?strlen(szBuf),?&nWriteByte,?NULL?)?;??
  74. ????pMyDlg->SetDlgItemInt?(?IDC_FIRST,?a,?true?)?;??
  75. ????pMyDlg->SetDlgItemInt?(?IDC_SECOND,?b,?true?)?;??
  76. ????pMyDlg->SetDlgItemInt?(?IDC_RESULT,?pMyDlg->nResValue,?true?)?;??
  77. ????//?斷開客戶端的連接,以便等待下一客戶的到來??
  78. ????DisconnectNamedPipe?(?CurPipeInst.hPipe?)?;??
  79. ??}??
  80. ??
  81. ??return?0?;??
  82. }??
最后特別說明一下,此文章是看雪WIN32安全編程板塊的斑竹北極星的,大家可以多多關注一下他的技術文章,看了幾篇都認為很不錯的。
鏈 接:?http://bbs.pediy.com/showthread.php?t=26252
http://blog.csdn.net/yiruirui0507/article/details/6457806

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458329.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458329.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458329.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端知識體系收藏

1. 布局框架&#xff1a; Bootstrap: http://getbootstrap.com/ Foundation: http://foundation.zurb.com/ Uikit: http://www.getuikit.com/ Web Components:http://css-tricks.com/modular-future-web-components// 2. 構建工具及包管理器&#xff1a; Grunt: http://gruntjs…

20分鐘快速了解Redis

Redis可以說是目前最火爆的NoSQL數據庫&#xff01; 過去幾年&#xff0c;Memcached很盛行&#xff0c;現在有很多公司已將Memcached替換成了Redis。當然&#xff0c;很多人替換并不清楚為什么&#xff0c;只是感覺不想讓主流拋棄&#xff0c;這也充分反映了目前Redis的強勢。 …

進程通信例子

from&#xff1a;https://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.beginoutputreadline(vvs.80).aspx?cs-save-lang1&cs-langcsharp#code-snippet-4備注可同步或異步讀取 StandardOutput 流。Read、ReadLine 和 ReadToEnd 等方法對進程的輸出流執行…

IDEA15 下運行Scala遇到問題以及解決辦法

為了讓Scala運行起來還是很麻煩&#xff0c;為了大家方便&#xff0c;還是記錄下來&#xff1a; 1、首先我下載的是IDEA的社區版本&#xff0c;版本號為15. 2、下載安裝scala插件&#xff1a; 2.1 進入設置菜單。 2.2 點擊安裝JetBrains plugin 2.3 輸入scala查詢插件&#xff…

通過掃碼自定義鏈接安裝iOS app,版本更新總結。

1、打包ipa&#xff0c;plist工具&#xff1a;xcode6證書&#xff1a;企業級開發證書 1.1&#xff09;xcode6開始企業級打包時不在生成plist&#xff0c;需要自己編寫&#xff1a;模版見下&#xff1a; <?xml version"1.0" encoding"UTF-8"?><!…

安排與愿想

機器學習的理論學了好久了&#xff0c;對于回歸&#xff0c;分類&#xff0c;聚類&#xff0c;數據的預處理的各種算法也有了深刻認識&#xff1b; 但紙上談兵&#xff0c;沒有意義&#xff1b; 從今天開始用起來吧&#xff0c;把各種算法的實踐以及思路記錄下來&#xff0c;附…

pdf破解版

網頁說明http://aikongke.com/3754.html1118-1805-7284-0295-8107-3663您好 親 看到您拍的寶貝了&#xff01; 鏈接&#xff1a;http://pan.baidu.com/s/1c0iE44C 密碼&#xff1a;bnyc XI版轉載于:https://www.cnblogs.com/computerMatainance/p/5192834.html

使用try-with-resources替代try finally釋放資源

2019獨角獸企業重金招聘Python工程師標準>>> 1、舊社會 Java里&#xff0c;對于文件操作IO流、數據庫連接等開銷非常昂貴的資源&#xff0c;用完之后必須及時通過close方法將其關閉&#xff0c;否則資源會一直處于打開狀態&#xff0c;直至程序停止&#xff0c;增加…

MFC模態對話框和非模態對話框

MFC中對話框有兩種形式&#xff0c;一個是模態對話框&#xff08;model dialog box&#xff09;&#xff0c;一個是非模態對話框&#xff08;modeless dialog box&#xff09;。一、模態對話框&#xff08;model dialog box&#xff09;在程序運行的過程中&#xff0c;若出現了…

平板電腦離壽終正寢還有多遠?

近期有評論稱&#xff0c;因為大尺寸智能手機越來越普及&#xff0c;小尺寸平板正遭受著越來越嚴重的沖擊&#xff0c;在這樣的背景下&#xff0c;平板廠商也紛紛轉攻超大尺寸平板市場&#xff0c;以此避開大尺寸智能手機的競爭&#xff0c;只是。這樣的策略轉變是否能扭轉平板…

Swift 與 JSON 數據

轉載自&#xff1a; http://www.cnblogs.com/theswiftworld/p/4660177.html 我們大家平時在開發 App 的時候&#xff0c;相信接觸最多的就是 JSON 數據了。只要你的 App 有讀取網絡數據的功能&#xff0c;你就免不了要與 JSON 打交道。比如你做一個新聞 App&#xff0c;你要讀取…

TeamViewer - 最好用強大的免費跨平臺遠程桌面控制軟件 (支持電腦和手機)

from&#xff1a;很早以前 LYcHEE 就提到過&#xff0c;家中的潮人爺爺奶奶每天擺弄著電腦&#xff0c;看看新聞發發郵件&#xff0c;安享晚年生活。只是意料之中的&#xff0c;電腦上莫名出現各種問題&#xff1f;不翼而飛的圖標&#xff1f;照片又忘記怎么導出了&#xff1f;…

【設計模式】7、橋接模式

橋接模式就是對一個類的方法進行抽象化&#xff0c;吧不相關的因素提取出來&#xff0c;發展出第二個類 1 package com.shejimoshi.structural.Bridge;2 3 4 /**5 * 功能&#xff1a;橋接模式使用6 * 意圖&#xff1a;將抽象部分與它的實現部分分離&#xff0c;使他們都…

hadoop HA 之 QJM

前言 本文主要通過對hadoop2.2.0集群配置的過程加以梳理&#xff0c;所有的步驟都是通過自己實際測試。文檔的結構也是根據自己的實際情況而定&#xff0c;同時也會加入自己在實際過程遇到的問題。搭建環境過程不重要&#xff0c;重要點在于搭建過程中遇到的問題&#xff0c;解…

TeamViewer免費版和付費版有什么不同

提到遠程控制軟件 TeamViewer無疑是目前業內知名度比較高的一款&#xff0c;所以說到遠程控制軟件可能大部分人首先想到的就是TeamViewer。在使用功能上&#xff0c;它支持遠程桌面控制、文件傳輸、遠程計算機鎖定、視頻會話、主控方和被控方身份互換&#xff0c;遠程管理無人執…

iOS-關于cell的重疊問題

記得很早之前遇到過一個問題&#xff0c;關于cell的重疊問題&#xff0c;現在回顧總結一下。 iOS中tableview的cell顯示是會消耗內存的&#xff0c;如果要顯示無數個cell&#xff0c;不可能把每個cell都存儲下來&#xff0c;為了解決這個問題&#xff0c;cell就用了重用機制&am…

每天一個Linux命令-ls

ls 命令在linux系統中是使用頻率最頻繁的幾個命令之一,直接使用不帶目錄名&#xff0c;是默認顯示當前目錄的文件及子目錄名稱&#xff0c;ls加指定目錄名&#xff0c;則可以查看指定目錄下的文件及子目錄名稱&#xff0c;ls不僅可以查看目錄下有哪些文件和子目錄&#xff0c;還…

halcon資料鏈接

本文轉載自xiamentingtao&#xff0c;原文地址如下&#xff1a; http://blog.csdn.net/xiamentingtao/article/details/52583787 1目錄(?)[]論壇培訓博客文檔書籍視頻論壇、培訓halcon學習網&#xff1a;http://www.ihalcon.com/鳥叔機器視覺&#xff1a;http://bbs.szvbt.com…

【代碼筆記】iOS-翻書效果的實現

代碼&#xff1a; RootViewController.m #import "RootViewController.h"interface RootViewController ()endimplementation RootViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {self [super initWithNibName:…

修改TFS與本地源代碼映射路徑

使用源代碼管理資源管理器修改工作區 在“文件”菜單上單擊“源代碼管理”&#xff0c;再單擊“工作區”。 在“管理工作區”對話框的“名稱”列下&#xff0c;突出顯示要修改的工作區&#xff0c;然后單擊“編輯”。 在“編輯工作區”對話框中&#xff1a; 修改“名稱”框中…