简述

Crypto++库是一个用c++ 编写的密码类库,是一个自由软件。有关它的信息可以访问以下两个网站:

下载

进入Crypto++主页,下载对应的版本(我下载的是最新的:Crypto++ 5.6.3

解压缩之后,我们会看到里面包含大量的头文件、源文件、以及工程文件,用VS2013打开cryptest.sln,然后进行编译(清理->重新生成)即可。

编译完成,会生成cryptest.exe、cryptlib.lib(E:\Crypto++5.6.3\Win32\Output\Debug)。

使用

新建一个Win32控制台应用程序TestCrypto++。

  1. 右键“属性”,选择“配置属性”-> C/C++ ->常规,附加包含目录E:\Crypto++5.6.3
  2. 右键“属性”,选择“配置属性”-> 链接器 ->常规,附加库目录E:\Crypto++5.6.3\Win32\Output\Debug
  3. 右键“属性”,选择“配置属性”-> C/C++ -> 代码生成,运行库选择“多线程调试(/MTd)”(Release模式下对应“多线程(/MT)”)。

此时,使用Crypto++的开发环境就搭建好了,在Crypto++ User Guide中的例子。

AES加解密

Ok,编写测试程序。。。

效果

源码

  1. // TestCrypto++.cpp : 定义控制台应用程序的入口点。
  2. #include "stdafx.h"
  3. #include <aes.h>
  4. #include <Hex.h> // StreamTransformationFilter
  5. #include <modes.h> // CFB_Mode
  6. #include <iostream> // std:cerr
  7. #include <sstream> // std::stringstream
  8. #include <string>
  9. using namespace std;
  10. using namespace CryptoPP;
  11. #pragma comment(lib, "cryptlib.lib" )
  12. std::string ECB_AESEncryptStr(std::string sKey, const char *plainText)
  13. {
  14. std::string outstr;
  15. //填key
  16. SecByteBlock key(AES::MAX_KEYLENGTH);
  17. memset(key, 0x30, key.size());
  18. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  19. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
  20. ECB_Mode_ExternalCipher::Encryption ecbEncryption(aesEncryption);
  21. StreamTransformationFilter ecbEncryptor(ecbEncryption, new HexEncoder(new StringSink(outstr)));
  22. ecbEncryptor.Put((byte *)plainText, strlen(plainText));
  23. ecbEncryptor.MessageEnd();
  24. return outstr;
  25. }
  26. std::string ECB_AESDecryptStr(std::string sKey, const char *cipherText)
  27. {
  28. std::string outstr;
  29. //填key
  30. SecByteBlock key(AES::MAX_KEYLENGTH);
  31. memset(key, 0x30, key.size());
  32. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  33. ECB_Mode<AES >::Decryption ecbDecryption((byte *)key, AES::MAX_KEYLENGTH);
  34. HexDecoder decryptor(new StreamTransformationFilter(ecbDecryption, new StringSink(outstr)));
  35. decryptor.Put((byte *)cipherText, strlen(cipherText));
  36. decryptor.MessageEnd();
  37. return outstr;
  38. }
  39. std::string CBC_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
  40. {
  41. std::string outstr;
  42. //填key
  43. SecByteBlock key(AES::MAX_KEYLENGTH);
  44. memset(key, 0x30, key.size());
  45. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  46. //填iv
  47. byte iv[AES::BLOCKSIZE];
  48. memset(iv, 0x30, AES::BLOCKSIZE);
  49. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  50. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
  51. CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
  52. StreamTransformationFilter cbcEncryptor(cbcEncryption, new HexEncoder(new StringSink(outstr)));
  53. cbcEncryptor.Put((byte *)plainText, strlen(plainText));
  54. cbcEncryptor.MessageEnd();
  55. return outstr;
  56. }
  57. std::string CBC_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
  58. {
  59. std::string outstr;
  60. //填key
  61. SecByteBlock key(AES::MAX_KEYLENGTH);
  62. memset(key, 0x30, key.size());
  63. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  64. //填iv
  65. byte iv[AES::BLOCKSIZE];
  66. memset(iv, 0x30, AES::BLOCKSIZE);
  67. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  68. CBC_Mode<AES >::Decryption cbcDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
  69. HexDecoder decryptor(new StreamTransformationFilter(cbcDecryption, new StringSink(outstr)));
  70. decryptor.Put((byte *)cipherText, strlen(cipherText));
  71. decryptor.MessageEnd();
  72. return outstr;
  73. }
  74. std::string CBC_CTS_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
  75. {
  76. std::string outstr;
  77. //填key
  78. SecByteBlock key(AES::MAX_KEYLENGTH);
  79. memset(key, 0x30, key.size());
  80. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  81. //填iv
  82. byte iv[AES::BLOCKSIZE];
  83. memset(iv, 0x30, AES::BLOCKSIZE);
  84. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  85. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
  86. CBC_CTS_Mode_ExternalCipher::Encryption cbcctsEncryption(aesEncryption, iv);
  87. StreamTransformationFilter cbcctsEncryptor(cbcctsEncryption, new HexEncoder(new StringSink(outstr)));
  88. cbcctsEncryptor.Put((byte *)plainText, strlen(plainText));
  89. cbcctsEncryptor.MessageEnd();
  90. return outstr;
  91. }
  92. std::string CBC_CTS_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
  93. {
  94. std::string outstr;
  95. //填key
  96. SecByteBlock key(AES::MAX_KEYLENGTH);
  97. memset(key, 0x30, key.size());
  98. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  99. //填iv
  100. byte iv[AES::BLOCKSIZE];
  101. memset(iv, 0x30, AES::BLOCKSIZE);
  102. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  103. CBC_CTS_Mode<AES >::Decryption cbcctsDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
  104. HexDecoder decryptor(new StreamTransformationFilter(cbcctsDecryption, new StringSink(outstr)));
  105. decryptor.Put((byte *)cipherText, strlen(cipherText));
  106. decryptor.MessageEnd();
  107. return outstr;
  108. }
  109. std::string CFB_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
  110. {
  111. std::string outstr;
  112. //填key
  113. SecByteBlock key(AES::MAX_KEYLENGTH);
  114. memset(key, 0x30, key.size());
  115. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  116. //填iv
  117. byte iv[AES::BLOCKSIZE];
  118. memset(iv, 0x30, AES::BLOCKSIZE);
  119. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  120. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
  121. CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv);
  122. StreamTransformationFilter cfbEncryptor(cfbEncryption, new HexEncoder(new StringSink(outstr)));
  123. cfbEncryptor.Put((byte *)plainText, strlen(plainText));
  124. cfbEncryptor.MessageEnd();
  125. return outstr;
  126. }
  127. std::string CFB_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
  128. {
  129. std::string outstr;
  130. //填key
  131. SecByteBlock key(AES::MAX_KEYLENGTH);
  132. memset(key, 0x30, key.size());
  133. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  134. //填iv
  135. byte iv[AES::BLOCKSIZE];
  136. memset(iv, 0x30, AES::BLOCKSIZE);
  137. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  138. CFB_Mode<AES >::Decryption cfbDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
  139. HexDecoder decryptor(new StreamTransformationFilter(cfbDecryption, new StringSink(outstr)));
  140. decryptor.Put((byte *)cipherText, strlen(cipherText));
  141. decryptor.MessageEnd();
  142. return outstr;
  143. }
  144. std::string OFB_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
  145. {
  146. std::string outstr;
  147. //填key
  148. SecByteBlock key(AES::MAX_KEYLENGTH);
  149. memset(key, 0x30, key.size());
  150. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  151. //填iv
  152. byte iv[AES::BLOCKSIZE];
  153. memset(iv, 0x30, AES::BLOCKSIZE);
  154. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  155. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
  156. OFB_Mode_ExternalCipher::Encryption ofbEncryption(aesEncryption, iv);
  157. StreamTransformationFilter ofbEncryptor(ofbEncryption, new HexEncoder(new StringSink(outstr)));
  158. ofbEncryptor.Put((byte *)plainText, strlen(plainText));
  159. ofbEncryptor.MessageEnd();
  160. return outstr;
  161. }
  162. std::string OFB_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
  163. {
  164. std::string outstr;
  165. //填key
  166. SecByteBlock key(AES::MAX_KEYLENGTH);
  167. memset(key, 0x30, key.size());
  168. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  169. //填iv
  170. byte iv[AES::BLOCKSIZE];
  171. memset(iv, 0x30, AES::BLOCKSIZE);
  172. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  173. OFB_Mode<AES >::Decryption ofbDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
  174. HexDecoder decryptor(new StreamTransformationFilter(ofbDecryption, new StringSink(outstr)));
  175. decryptor.Put((byte *)cipherText, strlen(cipherText));
  176. decryptor.MessageEnd();
  177. return outstr;
  178. }
  179. std::string CTR_AESEncryptStr(std::string sKey, std::string sIV, const char *plainText)
  180. {
  181. std::string outstr;
  182. //填key
  183. SecByteBlock key(AES::MAX_KEYLENGTH);
  184. memset(key, 0x30, key.size());
  185. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  186. //填iv
  187. byte iv[AES::BLOCKSIZE];
  188. memset(iv, 0x30, AES::BLOCKSIZE);
  189. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  190. AES::Encryption aesEncryption((byte *)key, AES::MAX_KEYLENGTH);
  191. CTR_Mode_ExternalCipher::Encryption ctrEncryption(aesEncryption, iv);
  192. StreamTransformationFilter ctrEncryptor(ctrEncryption, new HexEncoder(new StringSink(outstr)));
  193. ctrEncryptor.Put((byte *)plainText, strlen(plainText));
  194. ctrEncryptor.MessageEnd();
  195. return outstr;
  196. }
  197. std::string CTR_AESDecryptStr(std::string sKey, std::string sIV, const char *cipherText)
  198. {
  199. std::string outstr;
  200. //填key
  201. SecByteBlock key(AES::MAX_KEYLENGTH);
  202. memset(key, 0x30, key.size());
  203. sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
  204. //填iv
  205. byte iv[AES::BLOCKSIZE];
  206. memset(iv, 0x30, AES::BLOCKSIZE);
  207. sIV.size() <= AES::BLOCKSIZE ? memcpy(iv, sIV.c_str(), sIV.size()) : memcpy(iv, sIV.c_str(), AES::BLOCKSIZE);
  208. CTR_Mode<AES >::Decryption ctrDecryption((byte *)key, AES::MAX_KEYLENGTH, iv);
  209. HexDecoder decryptor(new StreamTransformationFilter(ctrDecryption, new StringSink(outstr)));
  210. decryptor.Put((byte *)cipherText, strlen(cipherText));
  211. decryptor.MessageEnd();
  212. return outstr;
  213. }
  214. int _tmain(int argc, _TCHAR* argv[])
  215. {
  216. string plainText = "This Program shows how to use ECB, CBC, CBC_CTS, CFB, OFB and CTR mode of AES in Crypto++.";
  217. string aesKey = "0123456789ABCDEF0123456789ABCDEF";//256bits, also can be 128 bits or 192bits
  218. string aesIV = "ABCDEF0123456789";//128 bits
  219. string ECB_EncryptedText, ECB_DecryptedText,
  220. CBC_EncryptedText, CBC_DecryptedText,
  221. CBC_CTS_EncryptedText, CBC_CTS_DecryptedText,
  222. CFB_EncryptedText, CFB_DecryptedText,
  223. OFB_EncryptedText, OFB_DecryptedText,
  224. CTR_EncryptedText, CTR_DecryptedText;
  225. //ECB
  226. ECB_EncryptedText = ECB_AESEncryptStr(aesKey, plainText.c_str());//ECB加密
  227. ECB_DecryptedText = ECB_AESDecryptStr(aesKey, ECB_EncryptedText.c_str());//ECB解密
  228. //CBC
  229. CBC_EncryptedText = CBC_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CBC加密
  230. CBC_DecryptedText = CBC_AESDecryptStr(aesKey, aesIV, CBC_EncryptedText.c_str());//CBC解密
  231. //CBC_CTS
  232. CBC_CTS_EncryptedText = CBC_CTS_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CBC_CTS加密
  233. CBC_CTS_DecryptedText = CBC_CTS_AESDecryptStr(aesKey, aesIV, CBC_CTS_EncryptedText.c_str());//CBC_CTS解密
  234. //CFB
  235. CFB_EncryptedText = CFB_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CFB加密
  236. CFB_DecryptedText = CFB_AESDecryptStr(aesKey, aesIV, CFB_EncryptedText.c_str());//CFB解密
  237. //OFB
  238. OFB_EncryptedText = OFB_AESEncryptStr(aesKey, aesIV, plainText.c_str());//OFB加密
  239. OFB_DecryptedText = OFB_AESDecryptStr(aesKey, aesIV, OFB_EncryptedText.c_str());//OFB解密
  240. //CTR
  241. CTR_EncryptedText = CTR_AESEncryptStr(aesKey, aesIV, plainText.c_str());//CTR加密
  242. CTR_DecryptedText = CTR_AESDecryptStr(aesKey, aesIV, CTR_EncryptedText.c_str());//CTR解密
  243. cout << "Crypto++ AES-256 加密测试" << endl;
  244. cout << "分别使用ECB,CBC, CBC_CTR,CFB,OFB和CTR模式" << endl;
  245. cout << "加密用密钥:" << aesKey << endl;
  246. cout << "密钥长度:" << AES::MAX_KEYLENGTH * 8 << "bits" << endl;
  247. cout << "IV:" << aesIV << endl;
  248. cout << endl;
  249. cout << "ECB测试" << endl;
  250. cout << "原文:" << plainText << endl;
  251. cout << "密文:" << ECB_EncryptedText << endl;
  252. cout << "恢复明文:" << ECB_DecryptedText << endl << endl;
  253. cout << "CBC测试" << endl;
  254. cout << "原文:" << plainText << endl;
  255. cout << "密文:" << CBC_EncryptedText << endl;
  256. cout << "恢复明文:" << CBC_DecryptedText << endl << endl;
  257. cout << "CBC_CTS测试" << endl;
  258. cout << "原文:" << plainText << endl;
  259. cout << "密文:" << CBC_CTS_EncryptedText << endl;
  260. cout << "恢复明文:" << CBC_CTS_DecryptedText << endl << endl;
  261. cout << "CFB测试" << endl;
  262. cout << "原文:" << plainText << endl;
  263. cout << "密文:" << CFB_EncryptedText << endl;
  264. cout << "恢复明文:" << CFB_DecryptedText << endl << endl;
  265. cout << "OFB测试" << endl;
  266. cout << "原文:" << plainText << endl;
  267. cout << "密文:" << OFB_EncryptedText << endl;
  268. cout << "恢复明文:" << OFB_DecryptedText << endl << endl;
  269. cout << "CTR测试" << endl;
  270. cout << "原文:" << plainText << endl;
  271. cout << "密文:" << CTR_EncryptedText << endl;
  272. cout << "恢复明文:" << CTR_DecryptedText << endl << endl;
  273. getchar();
  274. return 0;
  275. }

更多参考

http://blog.csdn.net/u011012932/article/details/51659452

Crypto++编译使用的更多相关文章

  1. librtmp编译for android and ios 不要openssl

    git clone git://git.ffmpeg.org/rtmpdump 不想要openssl 在rtmp.h里面 #undef CRYPTO 编译动态库与静态库只需要修改下面的 #includ ...

  2. pamamiko的安装

    pamiko的安装 Paramiko的安装依赖第三方的crypto,ecdsa,及python开发包的python-devel的支持,源码包安装如下 安装 安装paramiko有两个先决条件,pyth ...

  3. 使用Crypto++库编译出错 解决办法

    错误信息: >------ 已启动生成: 项目: testCrypto++, 配置: Debug Win32 ------ >正在编译... >main.cpp >正在链接.. ...

  4. pom里引入lib下的包后编译报 package com.sun.crypto.provider does not exist问题解决

    最近正在迭代开发的一个项目编译安装时出现报“package com.sun.crypto.provider does not exist”的错误,由于本人能力水平有限,也是第一次遇到该问题,来来回回折 ...

  5. Crypto++ 动态链接编译与实例测试

    测试用例的来源<Crypto++入门学习笔记(DES.AES.RSA.SHA-256)> 解决在初始化加密器对象时触发异常的问题: CryptoPP::AESEncryption aesE ...

  6. Maven打包编译找不到com.sun.crypto.provider.SunJCE类

    Maven配置 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>mav ...

  7. Linux内核配置、编译及Makefile简述

    Hi,大家好!我是CrazyCatJack.最近在学习Linux内核的配置.编译及Makefile文件.今天总结一下学习成果,分享给大家^_^ 1.解压缩打补丁 首先是解压缩你获取到的Linux内核. ...

  8. [No0000AB]用Visual Studio 2015在 WIN10 64bit 上编译7-zip (32 bit)

    1.7-ZIP简介 7-zip 是一款免费的压缩解压软件.ZIP格式的文件默认被苹果和微软支持,完全不需要额外安装其他软件就可以解压.但对于非US-ASCII编码的文件名和大于2GB的ZIP文件,可能 ...

  9. centos下编译安装lnmp

    centos下编译安装lnmp 本文以centos为背景在其中编译安装nginx搭建lnmp环境. 编译安装nginx时,需要事先安装 开发包组"Development Tools" ...

随机推荐

  1. NABC的特点分析

    题目:                         请把采用卡片分类的方法讨论你们的团队开发项目特点,再按照 NABC 的框架分析每个特点. 每一个组员针对其中的一个特点将NABC的分析结果发表博 ...

  2. Eigen库实现简单的旋转、平移操作

    本来课程要求用GUI界面来实现Eigen的旋转.平移操作的,但是接触GUI编程时间太短,虽然要求很简单,但是做了几天还是没有完成.就把命令行下面的简单的贴一下吧. main.cpp #include ...

  3. centos中设置apache显示目录列表

    apache中显示目录列表 在http.conf中加入如下代码(如有虚拟主机配置,加在虚拟主机配置段内),并把主目录内的index.pho,index.html,index.htm文件删除 复制代码  ...

  4. MVC4 网站发布(整理 + 部分转载 + 部分问题收集和解决方案)

    网站发布步骤: 这部分是转载文章 在此标明出处,以前有文章是转的没标明的请谅解,因为有些已经无法找到出处,或者与其它原因. 如有冒犯请联系本人,或删除,或标明出处. 因为好的文章,以前只想收藏,但连接 ...

  5. 百度地图之POI

    // // PoiViewController.m // baiDuDemo // // Created by City--Online on 15/6/4. // Copyright (c) 201 ...

  6. input.nextLine() 问题出错!

    今天在学习关于I/O的知识的时候发现了一个小问题! 代码如下 package com.paulo.testio; import java.io.File; import java.io.IOExcep ...

  7. spring--注入类型--构造方法(不常用)

    3.3.1.1. Constructor Injection Constructor-based DI is effected by invoking a constructor with a num ...

  8. 802.11 wireless 五

    802.11 wireless 5CSMA/CA,采用倒计时的方法,退避的时间(当年时间+duration 为发送时间,每一个帧会有一个duration,这个位叫做duration[n.持续]) PS ...

  9. Oracle NULL 和空值

      如果你工作中用到了Oracle,你必须要留意NULL和空值的处理与SQL Server上的不同.现在让我们看些例子. 建立这张数据库表并插入记录 CREATE TABLE TestNull(Col ...

  10. Linux 的多线程编程的高效开发经验

    http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/ 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多 ...