C++ REST SDK

簡(jiǎn)介

c++REST SDK琼懊,又叫卡薩布蘭卡是一個(gè)微軟發(fā)布的C++基于云的客戶機(jī)-服務(wù)器通信庫(kù)。該庫(kù)基于現(xiàn)代化的C++異步API爬早,即Promise模型或叫鏈?zhǔn)疆惒侥P驮O(shè)計(jì)[1]哼丈,c++開(kāi)發(fā)人員可以方便地連接并與服務(wù)交互。

SDK內(nèi)容

  • 特性——HTTP客戶機(jī)/服務(wù)器筛严,JSON醉旦,URI,異步流桨啃,WebSockets客戶機(jī),oAuth
  • PPL任務(wù)[2] ——一個(gè)強(qiáng)大的基于c++11特性編寫(xiě)的異步操作模型
  • 支持平臺(tái)——Windows桌面车胡,Windows Store,Windows Phone照瘾,Ubuntu匈棘,OS X,iOS和Android
  • Windows平臺(tái)編譯支持——VS 2012析命,2013年和2015
  • 非Windows平臺(tái)編譯支持——cmake
  • 包管理器支持——NuGet主卫,僅在VS編譯器支持Windows和Android平臺(tái)[3]

Http Client示例

#include <cpprest/http_client.h>
#include <cpprest/filestream.h>

using namespace utility;                    // Common utilities like string conversions
using namespace web;                        // Common features like URIs.
using namespace web::http;                  // Common HTTP functionality
using namespace web::http::client;          // HTTP client features
using namespace concurrency::streams;       // Asynchronous streams

int main(int argc, char* argv[])
{
    auto fileStream = std::make_shared<ostream>();

    // Open stream to output file.
    pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
    {
        *fileStream = outFile;

        // Create http_client to send the request.
        http_client client(U("http://www.bing.com/"));

        // Build request URI and start the request.
        uri_builder builder(U("/search"));
        builder.append_query(U("q"), U("cpprestsdk github"));
        return client.request(methods::GET, builder.to_string());
    })

    // Handle response headers arriving.
    .then([=](http_response response)
    {
        printf("Received response status code:%u\n", response.status_code());

        // Write response body into the file.
        return response.body().read_to_end(fileStream->streambuf());
    })

    // Close the file stream.
    .then([=](size_t)
    {
        return fileStream->close();
    });

    // Wait for all the outstanding I/O to complete and handle any exceptions
    try
    {
        requestTask.wait();
    }
    catch (const std::exception &e)
    {
        printf("Error exception:%s\n", e.what());
    }

    return 0;
}

JSON

構(gòu)造JSON

JSON是JavaScript Object Notation,也就是JS對(duì)象表示法的簡(jiǎn)稱鹃愤。由于它的簡(jiǎn)單簇搅,緊湊,靈活软吐,占用空間小瘩将,與JS無(wú)縫銜接等優(yōu)點(diǎn),近年來(lái)已經(jīng)替代xml成為web通信的主要信息載體关噪。在cpprest中鸟蟹,JSON值是由web::json::value類來(lái)表示的,不管它是一個(gè)數(shù)值使兔,一個(gè)字符串,或者一個(gè)對(duì)象藤韵,它都可以是一個(gè)JSON值虐沥。正是由于JSON可以表示任何靜態(tài)數(shù)據(jù)類型,所以有不少語(yǔ)言有不少庫(kù)支持JSON對(duì)象和編程語(yǔ)言對(duì)象的直接映射泽艘,但這些庫(kù)在提高編碼效率的同時(shí)欲险,也都有或多或少的問(wèn)題,有的有性能問(wèn)題匹涮,有的對(duì)代碼有侵入性天试,如必須繼承某一基類,需要謹(jǐn)慎選用然低。
構(gòu)建一個(gè)JSON值喜每,最簡(jiǎn)單的方式务唐,我們可以通過(guò)使用普通的c++值來(lái)構(gòu)建。cpprest提供了一個(gè)重載的工廠函數(shù)带兜,該函數(shù)可以構(gòu)建6種類型的JSON值枫笛,示例如下:

using namespace web;
...
json::value v0 = json::value::null();
json::value v1 = json::value::number(17);
json::value v2 = json::value::number(3.1415);
json::value v3 = json::value::boolean(true);
json::value v4 = json::value::string(U("Hello Again!"));
json::value v5 = json::value::object();
json::value v6 = json::value::array();

解析和序列化

對(duì)于JSON來(lái)說(shuō),幾乎所有實(shí)際中的使用刚照,都是將類型轉(zhuǎn)化成JSON或從JSON轉(zhuǎn)化成相應(yīng)的類型刑巧,所以一個(gè)常見(jiàn)的構(gòu)建JSON的方式,就是通過(guò)解析无畔。
我們可以通過(guò)解析的方法從一個(gè)流或字符串中生成一個(gè)JSON啊楚,如:

using namespace web;
...
utility::stringstream_t ss1;
ss1 << U("17");
json::value v1 = json::value::parse(ss1);

相反的方向也同樣簡(jiǎn)單:

using namespace web;
...
utility::stringstream_t stream;
json::value v1 = json::value::string(U("Hi"));
v1.serialize(stream);

訪問(wèn)數(shù)據(jù)

除了添加元素,添加字段和寫(xiě)JSON值到一個(gè)流中浑彰,對(duì)一個(gè)JSON來(lái)說(shuō)特幔,沒(méi)太多操作可做:因?yàn)镴SON并不是用于作為一個(gè)通用的動(dòng)態(tài)數(shù)值系統(tǒng)來(lái)設(shè)計(jì)的,他的主要作用就是對(duì)JSON對(duì)象做讀寫(xiě)操作闸昨。對(duì)于一個(gè)的值處理蚯斯,還是應(yīng)該仰仗于C++系統(tǒng),所以我們就需要一種從JSON對(duì)象得到C++值的方法饵较。cpprest強(qiáng)迫我們從JSON中取值時(shí)拍嵌,通過(guò)使用"as_xxx()"這樣的函數(shù)來(lái)明確指定C++類型,而不是提供隱式轉(zhuǎn)換操作循诉,如:

int i = v1.as_integer();
double d = v2.as_double();
bool b = v3.as_bool();
utility::string_t s = v4.as_string();

如果JSON內(nèi)部數(shù)據(jù)跟我們要求的類型不一致時(shí)横辆,轉(zhuǎn)換將拋出一個(gè)類型為json::json_exception的異常。如茄猫,當(dāng)要求轉(zhuǎn)換一個(gè)字符串到double或布爾時(shí)狈蚤,就發(fā)生失敗。訪問(wèn)JSON數(shù)組的單個(gè)或?qū)ο箢愋偷某蓡T變量有幾種方式划纽。其中一種方法就是使用[]函數(shù)脆侮,下標(biāo)操作符是非“常量”的操作,并且可以修改JSON值勇劣,在必要時(shí)靖避,會(huì)添加一個(gè)null值。

json::value obj = json::value::parse(U("{ \"a\" : 10 }"));
obj[U("a")] = json::value(12);
obj[U("b")] = json::value(13);
auto nullValue = obj[U("c")];

在上面的代碼中比默,字符串"a"的值幻捏,將從10變?yōu)?2,將在obj中添加一個(gè)"b"命咐,其值為13篡九,由于obj中沒(méi)有"c",直接讀取"c"時(shí)醋奠,將會(huì)返回一個(gè)null值榛臼。
通過(guò)不插入任何職方式訪問(wèn)JSON數(shù)組和對(duì)象時(shí)伊佃,可以使用json::value::at方法。如果值存在讽坏,則該方法就返回一個(gè)JSON值得引用锭魔,如果不存在,則拋出一個(gè)json::json_exeption異常路呜。

json::value obj = json::value::parse(U("{ \"a\" : 10 }"));
auto aValue = obj.at(U("a"));
auto bValue = obj.at(U("b"));

在上面的代碼中迷捧,調(diào)用"at"方法,訪問(wèn)"a"胀葱,將返回一個(gè)JSON數(shù)值10漠秋,而訪問(wèn)"b"將拋出異常。我們可以通過(guò)json::value::size()和json::value::has_field來(lái)檢測(cè)大小和一個(gè)JSON字段是否存在抵屿。
相比于其他類型庆锦,數(shù)值型操作,會(huì)多一個(gè)動(dòng)作轧葛,指定具體是哪種類型的數(shù)值搂抒,如:

json::value num = json::value(88);
int64_t num64 = num.as_number().to_int64();

WebSocket客戶端

關(guān)于websocekts所有相關(guān)的東西都在頭文件:ws_client.h,命名空間:web::web sockets::client尿扯。

#include <cpprest/ws_client.h>
using namespace web;
using namespace web::websockets::client;

websocket_client被用來(lái)創(chuàng)建 和維持一個(gè)到WebSocket端點(diǎn)的連接求晶。一旦你有你的客戶端,你就必須使用函數(shù)'connect()'連接到一個(gè)遠(yuǎn)端,并且傳入一個(gè)該客戶端要連接的URI衷笋,該函數(shù)會(huì)返回一個(gè)可以等待的pplx::task芳杏。

websocket_client client;
client.connect(U("ws://localhost:1234")).then([](){ /* We've finished connecting. */ });

一旦客戶端連接上,你就可以開(kāi)始發(fā)送和接受數(shù)據(jù)辟宗。就跟C++ Rest SDK的rest部分一樣爵赵,這是一異步的方式完成的。

websocket_outgoing_message msg;
msg.set_utf8_message("I am a UTF-8 string! (Or close enough...)");
client.send(msg).then([](){ /* Successfully sent the message. */ });

client.receive().then([](websocket_incoming_message msg) {
    return msg.extract_string();
}).then([](std::string body) {
    std::cout << body << std::endl;
});

(注意:每來(lái)一條消息泊脐,只有一個(gè)'receive()'函數(shù)會(huì)被調(diào)用)

我們支持發(fā)送和接收字符串和二進(jìn)制消息空幻。

websocket_outgoing_message msg;
concurrency::streams::producer_consumer_buffer<uint8_t> buf;
std::vector<uint8_t> body(6);
memcpy(&body[0], "a\0b\0c\0", 6);

auto send_task = buf.putn(&body[0], body.size()).then([&](size_t length) {
    msg.set_binary_message(buf.create_istream(), length);
    return client.send(msg);
}).then([](pplx::task<void> t)
{
    try
    {
        t.get();
    }
    catch(const websocket_exception& ex)
    {
        std::cout << ex.what();
    }
});
send_task.wait();

一旦結(jié)束,我們就應(yīng)該關(guān)閉它晨抡。

client.close().then([](){ /* Successfully closed the connection. */ });

有時(shí)甚至是大部分時(shí)候你從服務(wù)端接收許多消息氛悬,需要不斷地調(diào)用websocket_client::receive()并處理每個(gè)任務(wù),肯定是很繁瑣而且易錯(cuò)的耘柱,這時(shí)我們有另一個(gè)類websocket_callback_client,它允許設(shè)置一個(gè)回調(diào)函數(shù)來(lái)接收從服務(wù)器發(fā)來(lái)的消息棍现。注冊(cè)回調(diào)函數(shù)的實(shí)例如下:

websocket_callback_client client;
client.connect(U("ws://localhost:1234")).then([](){ /* We've finished connecting. */ });

// set receive handler
client.set_message_handler([](websocket_incoming_message msg)
{
    // handle message from server...
});


  1. 微軟把它稱作基于任務(wù)的異步編程 ?

  2. PPL调煎,全稱為Parallel Patterns Library,并行模式庫(kù)己肮,在cpprest中改名為pptx士袄,為了與ppl共存(ppl默認(rèn)存在于VS2012以上版本中) ?

  3. 部分語(yǔ)言包管理器:1 蘋(píng)果的XCode支持CocoaPods管理器悲关,同時(shí)支持Objective C和Swift開(kāi)發(fā)OS X和iOS應(yīng)用。 2 Java分別有ant(在主流項(xiàng)目開(kāi)發(fā)中娄柳,基本棄用)寓辱,maven(用xml管理第三方庫(kù))和gradle(用基于Groovy的動(dòng)態(tài)DSL管理第三方庫(kù)) ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赤拒,隨后出現(xiàn)的幾起案子秫筏,更是在濱河造成了極大的恐慌,老刑警劉巖挎挖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件这敬,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蕉朵,警方通過(guò)查閱死者的電腦和手機(jī)崔涂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)始衅,“玉大人冷蚂,你說(shuō)我怎么就攤上這事⊙凑ⅲ” “怎么了蝙茶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蛉拙。 經(jīng)常有香客問(wèn)我尸闸,道長(zhǎng),這世上最難降的妖魔是什么孕锄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任吮廉,我火速辦了婚禮,結(jié)果婚禮上畸肆,老公的妹妹穿的比我還像新娘宦芦。我一直安慰自己,他們只是感情好轴脐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布调卑。 她就那樣靜靜地躺著,像睡著了一般大咱。 火紅的嫁衣襯著肌膚如雪恬涧。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天碴巾,我揣著相機(jī)與錄音溯捆,去河邊找鬼。 笑死厦瓢,一個(gè)胖子當(dāng)著我的面吹牛提揍,可吹牛的內(nèi)容都是我干的啤月。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼劳跃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼谎仲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起刨仑,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤郑诺,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后贸人,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體间景,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年艺智,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倘要。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡十拣,死狀恐怖封拧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情夭问,我是刑警寧澤泽西,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站缰趋,受9級(jí)特大地震影響捧杉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秘血,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一味抖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧灰粮,春花似錦仔涩、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至柑肴,卻和暖如春霞揉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背晰骑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工零聚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人些侍。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓隶症,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親岗宣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚂会,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 目標(biāo) 對(duì)錘子有所了解的應(yīng)該知道3.0系統(tǒng)出了個(gè)叫“大爆炸”的功能,會(huì)將一段文本炸開(kāi)成一個(gè)個(gè)詞耗式,用來(lái)快速地“提取”信...
    長(zhǎng)不胖的Garfield閱讀 1,788評(píng)論 0 6
  • 目的 C++ REST SDK中的PPLX提供了基于任務(wù)的異步編程方案胁住,基于PPLX又提供了異步流,用來(lái)將輸入輸出...
    長(zhǎng)不胖的Garfield閱讀 3,106評(píng)論 0 3
  • 簡(jiǎn)介 C++ REST SDK中提供了PPLX用來(lái)支持異步操作刊咳,姑且可以認(rèn)為PPLX是微軟PPL-并行模式庫(kù)/并發(fā)...
    長(zhǎng)不胖的Garfield閱讀 9,290評(píng)論 0 2
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理彪见,服務(wù)發(fā)現(xiàn),斷路器娱挨,智...
    卡卡羅2017閱讀 134,672評(píng)論 18 139
  • 目標(biāo) 現(xiàn)在各大網(wǎng)站均可以使用一些已有其它賬戶(微信余指、微博等)登錄,而不需要為其申請(qǐng)賬戶和密碼跷坝,其中使用的授權(quán)協(xié)議有...
    長(zhǎng)不胖的Garfield閱讀 6,125評(píng)論 1 0