博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用C++访问Google API
阅读量:6975 次
发布时间:2019-06-27

本文共 4804 字,大约阅读时间需要 16 分钟。

  Google提供了一套基于SOAP的Web API提供给Web开发人员用于让我们可以更加便利的使用Google提供的服务,诸如相册、日历、文档等。可惜Google官方只提供了.net、JAVA、Python、PHP的库用于辅助编程,并没有提供C++的库。也许Google认为在这种Web开发中利用“原始”的C++着实是一件出力不讨好的事情。诚然 C++有速度上的优势,可是对比相对于高速运转的CPU来说,网络依旧是慢如蜗牛,等待的时间占了绝大多是,提升的性能空间着实有限。再者,C++开发难度高,人力时间成本大,往往为了解决这种小小的Web服务也不需要动用C++这种“牛刀”级别的工具。

  但是我们绝对不能说C++就完全不能运用在这里,事实上我们依旧可以利用C++进行访问,尤其是对本地执行环境有严格要求的情形,例如系统服务、嵌入式、无脚本和虚拟机执行环境的情况下,C++就成为了不二选择。本文主要展示的是用WinHTTP和ATL与Google Docs API进行通讯,提供给大家参考。

  使用Google API主要思路如下

  • 构造与Google保持连接的SSL连接
  • 获取授权码
  • 构造合适的HTTP请求头
  • 将我们的操作动作与授权码绑定在一起发送给Google
  • 接受处理数据,如果完成则关闭SSL连接,与Google断开

  首先解决第一个问题,就是构造SSL连接。我推荐使用OpenSSL或者是WinINet,前者跨平台,后者Windows XP系统及以上系统原生支持。所以如果我们希望跨平台则需要使用OpenSSL,如果仅仅在Windows平台下使用则无需其他辅助网络库。需要注意的是Python标准库中的urllib以及urllib2是原生支持SSL连接的,详细情况请看Python源代码。但是在ATL中并没有直接提供SSL连接的库,CAtlClient并没有加入对HTTPS的支持,所以我们需要手工利用WinINET构造HTTPS连接。示范代码如下,

ContractedBlock.gif
ExpandedBlockStart.gif
Code
HINTERNTE hInternet = InternetOpen("User", INTERNET_OPEN_TYPE_PRECONFIG , NULL, NULL, 0);//打开网络
HINTERNET hSession 
= InternetConnect(hInternet,"www.goole.com",443,"anonymous",NULL,INTERNET_SERVICE_HTTP,0,0);//开启会话
SecureFlag 
= INTERNET_FLAG_RELOAD|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_NO_CACHE_WRITE|      INTERNET_FLAG_SECURE|INTERNET_FLAG_IGNORE_CERT_CN_INVALID;//设置安全连接枚举参数
string AccountType("accountType=HOSTED_OR_GOOGLE"); 
string Email("&Email=youruser@gmail.com"); 
string Passwd("&Passwd=yourpassword"); 
string Service("&service=writely"); 
string Source("&source=abc-test-1.0");//这里都是用户的gmail帐号,而且我们访问的服务是Document List,服务名为writely
string AuthData = AccountType + Email + Passwd + Service + Source;
HINTERNET hAuthReq 
= HttpOpenRequest(hSession,"POST","/accounts/ClientLogin",NULL,NULL,NULL,SecureFlag,0);
HttpAddRequestHeaders(hAuthReq,
"Content-type: application/x-www-form-urlencoded\r\n",-1L,HTTP_ADDREQ_FLAG_ADD_IF_NEW);
HttpSendRequest(hReq,NULL,NULL,(LPVOID)AuthData.c_str(),AuthData.size());
string Result;
DWORD dwNumberOfBytesRead; 
char sz[4096];
int ReadLen; 
do { 
    ReadLen 
= InternetReadFile(hAuthReq, sz, 4095&dwNumberOfBytesRead);                                                
    sz[dwNumberOfBytesRead] 
= '\0'
    
int x = strlen(sz); 
    Result 
+= sz; 
    memset(sz, 
04096); 
while(result && dwNumberOfBytesRead != 0);    
InternetCloseHandle(hAuthReq);

 

这里我们就获得Google返回的验证信息,形式类似于这样,

 

ContractedBlock.gif
ExpandedBlockStart.gif
Code
SID=DQAAAHcAAAAYq…… 
LSID=DQAAAHcAAAAYq…… 
Auth=DQAAAHsAAAB……

 

根据Google的说明,我们下面发送的每一个请求都需要附加上Auth部分,我们下面需要的就是Auth作为验证信息访问Google API。首先祭出ATL获取当前所有的死人文档列表,代码如下

 

ContractedBlock.gif
ExpandedBlockStart.gif
Code
string AuthHeader("Authorization: GoogleLogin ");
AuthHeader 
+= Result.substr( Result.find("Auth="));//构造验证头
CAtlHttpClient Conn;
CAtlNavigateData NavData;
NavData.SetExtraHeaders(AuthHeader.c_str());
//加入刚才构造的头信息
NavData.SetMethod(L
"GET");//这里是GET操作
Conn.Navigate(
"http://docs.google.com/feeds/documents/private/full",&NavData);//获取数据
Conn.Close();
TiXmlDocument XmlDoc;
XmlDoc.Parse((
const char*)Conn.GetBody(),NULL,TIXML_ENCODING_UTF8);//如果没错的话可以使用TinyXML库进行结果分析了

 

Google API的第一步验证是不需要SSL客户验证的。根据Google API的文档说明,用户在使用API的时候需要保持验证连接的进行,所有的请求调用都需要附加上验证信息。Google API返回的所有字符都是UTF8编码,并且将本地ANSI文本上传之后多字节字符如中文将是乱码,所以我们需要将所有预备上传的字符都转换为UTF8格式再上传,否则在Google Docs内部看到的汉字都将是乱码。我们可以用下面的两个函数GBK与UTF8的转换,来自网络搜索,在此对原作者表示感谢,

 

void
 ConvertGBKToUtf8(CString
&
 strGBK) 
    
int
 len
=
MultiByteToWideChar(CP_ACP, 
0
, (LPCTSTR)strGBK, 
-
1
, NULL,
0
); 
    unsigned 
short
 
*
 wszUtf8 
=
 
new
 unsigned 
short
[len
+
1
]; 
    memset(wszUtf8, 
0
, len 
*
 
2
 
+
 
2
); 
    MultiByteToWideChar(CP_ACP, 
0
, (LPCTSTR)strGBK, 
-
1
, (LPWSTR)wszUtf8, len); 
    len 
=
 WideCharToMultiByte(CP_UTF8, 
0
, (LPWSTR)wszUtf8, 
-
1
, NULL, 
0
, NULL, NULL); 
    
char
 
*
szUtf8
=
new
 
char
[len 
+
 
1
]; 
    memset(szUtf8, 
0
, len 
+
 
1
); 
    WideCharToMultiByte (CP_UTF8, 
0
, (LPWSTR)wszUtf8, 
-
1
, szUtf8, len, NULL,NULL); 
    strGBK 
=
 szUtf8; 
    delete[] szUtf8; 
    delete[] wszUtf8; 
void
 ConvertUtf8ToGBK(CString
&
 strUtf8) { 
    
int
 len
=
MultiByteToWideChar(CP_UTF8, 
0
, (LPCTSTR)strUtf8, 
-
1
, NULL,
0
); 
    unsigned 
short
 
*
 wszGBK 
=
 
new
 unsigned 
short
[len
+
1
]; 
    memset(wszGBK, 
0
, len 
*
 
2
 
+
 
2
); 
    MultiByteToWideChar(CP_UTF8, 
0
, (LPCTSTR)strUtf8, 
-
1
, (LPWSTR)wszGBK, len); 
    len 
=
 WideCharToMultiByte(CP_ACP, 
0
, (LPWSTR)wszGBK, 
-
1
, NULL, 
0
, NULL, NULL); 
    
char
 
*
szGBK
=
new
 
char
[len 
+
 
1
]; 
    memset(szGBK, 
0
, len 
+
 
1
); 
    WideCharToMultiByte (CP_ACP, 
0
, (LPWSTR)wszGBK, 
-
1
, szGBK, len, NULL,NULL); 
    strUtf8 
=
 szGBK; 
    delete[] szGBK; 
    delete[] wszGBK; 
}

 

所有上传的文本都需要ConvertGBKToUtf8函数转换后再上传,下面是示范代码,

CAtlHttpClient Conn2;
CAtlNavigateData NavData;
NavData.SetExtraHeaders(AuthHeader.c_str());
NavData.SetMethod(
"
POST
"
);
CString SendData(
"
abcd中文dcba
"
);
ConvertGBKToUtf8(SendData);
NavData.SetPostData((BYTE
*
)SendData.GetBuffer(),SendData.GetLength(),
"
text/plain
"
)
Conn2.Navigate(
"
http://docs.google.com/feeds/documents/private/full
"
,
&
NavData);

 

  如果没有出错,此时Conn2的GetBody方法返回的是文件列表,如果没有加入Slug头,上传的文件名默认为Untitled。登录到docs.google.com,看看文件在不在那里了。根据这个思路我们可以访问Google提供的丰富服务而不需要浏览器,一定程度上可以实现自动化,本文仅仅是抛砖引玉,更加详细的实现请到code.google.com查询。

  版权所有,转载请联系我。

你可能感兴趣的文章
伯炎有话说:六大存疑拷问量子密码的安全
查看>>
云计算理解上四大误区
查看>>
基于SOA的企业IT架构
查看>>
NLP 专题论文解读:从 Chatbot 到 NER | PaperDaily #11
查看>>
最通俗易懂的解读比特币相关原理
查看>>
如何保证CAN网络中通讯的可靠性和节点数
查看>>
用C语言对Gtk+应用进行功能测试
查看>>
无聊时,可以去HASKELL里找点感觉
查看>>
江苏力推“不见面审批” 筹建省级大数据管理中心
查看>>
新华三下一代计算开启新格局
查看>>
杰和N60E-O荣获德国Hardwareinside金牌奖
查看>>
中国工程院院士刘韵洁:中国未来网络创新环境CENI的探索
查看>>
32个云服务通过第三批可信云服务认证 信用体系建设持续加力
查看>>
云生态:云计算棋局中的“胜负手”
查看>>
顺德拟投15亿元建大数据中心
查看>>
隐藏恶意软件的三大黑客技术
查看>>
《Spark与Hadoop大数据分析》——1.3 工具和技术
查看>>
数字时代反思竞争理论
查看>>
思科年中报告:坏人正变得更坏
查看>>
IDC:移动化发展增速 传统企业需要制定全方位移动战略
查看>>