溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++ 開(kāi)發(fā) Web 服務(wù)框架 - 基礎(chǔ)知識(shí):C++11 與 Boost Asio

發(fā)布時(shí)間:2020-06-29 15:55:15 來(lái)源:網(wǎng)絡(luò) 閱讀:1959 作者:一點(diǎn)寒芒 欄目:開(kāi)發(fā)技術(shù)

C++ 開(kāi)發(fā) Web 服務(wù)框架 - 基礎(chǔ)知識(shí):C++11 與 Boost Asio
一、概述

項(xiàng)目介紹

服務(wù)器開(kāi)發(fā)中 Web 服務(wù)是一個(gè)基本的代碼單元,將服務(wù)端的請(qǐng)求和響應(yīng)部分的邏輯抽象出來(lái)形成框架,能夠做到最高級(jí)別的框架級(jí)代碼復(fù)用。本次項(xiàng)目將綜合使用 C++11 及 Boost 中的 Asio 實(shí)現(xiàn) HTTP 和 HTTPS 的服務(wù)器框架。

項(xiàng)目涉及的知識(shí)點(diǎn)

C++基本知識(shí)
面向?qū)ο?br/>模板
命名空間
常用 IO 庫(kù)
C++11 相關(guān)
lambda expression
std::shared_ptr
std::make_shared
std::unordered_map
std::regex
std::smatch
std::regex_match
std::function
std::thread
Boost Asio 相關(guān)
boost::asio::io_service
boost::asio::ip::tcp::socket
boost::asio::ip::tcp::v4()
boost::asio::ip::tcp::endpoint
boost::asio::ip::tcp::acceptor
boost::asio::streambuf
boost::asio::async_read
boost::asio::async_read_until
boost::asio::async_write
boost::asio::transfer_exactly
boost::asio::ssl::stream
boost::asio::ssl::stream_base::server
boost::asio::ssl::context
boost::asio::ssl::context::sslv23
boost::asio::ssl::context::pem
boost::system::error_code
編譯環(huán)境提示

在 g++ 4.9 之前,regex 庫(kù)并不支持 ECMAScript 的正則語(yǔ)法,換句話說(shuō),在 g++4.9 之前,g++ 對(duì) C++11 標(biāo)準(zhǔn)庫(kù)的支持并不完善,為保證本次項(xiàng)目的順利進(jìn)行,請(qǐng)確保將 g++ 版本升級(jí)至 4.9 以上。

// 下面的這段代碼可以測(cè)試你的編譯器對(duì)正則表達(dá)式的支持情況
#include <iostream>
#include <regex>

int main()
{
std::regex r1("S");
printf("S works.\n");
std::regex r2(".");
printf(". works.\n");
std::regex r3(".+");
printf(".+ works.\n");
std::regex r4("[0-9]");
printf("[0-9] works.\n");
return 0;
}
如果你的運(yùn)行結(jié)果遇到了下圖所示的錯(cuò)誤,說(shuō)明你確實(shí)需要升級(jí)你的 g++ 了:

使用 g++ -v 可以查看到當(dāng)前編譯器版本:

如果你最后一行中的 gcc version 顯示的是 4.8.x,那么你需要手動(dòng)將編譯器版本升級(jí)至 4.9 以上,方法如下:

安裝 add-apt-repository 工具

sudo apt-get install software-properties-common

增加源

sudo add-apt-repository ppa:ubuntu-toolchain-r/test

更新源

sudo apt-get update

更新安裝

sudo apt-get upgrade

安裝 gcc/g++ 4.9

sudo apt-get install gcc-4.9 g++-4.9

更新鏈接

sudo updatedb
sudo ldconfig
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 48 \
--slave /usr/bin/g++ g++ /usr/bin/g++-4.8 \
--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-4.8 \
--slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-4.8 \
--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-4.8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 49 \
--slave /usr/bin/g++ g++ /usr/bin/g++-4.9 \
--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-4.9 \
--slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-4.9 \
--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-4.9
此外,本次項(xiàng)目依賴了 Boost 和 OpenSSL 這兩個(gè)庫(kù),不過(guò)好在實(shí)驗(yàn)樓的環(huán)境已經(jīng)提供了這兩個(gè)非?;镜膸?kù),你不需要再操心他們的安裝了。

項(xiàng)目代碼

本項(xiàng)目所有代碼

可使用wget下載,也可以直接復(fù)制地址到瀏覽器下載
希望同學(xué)們能跟著一步一步實(shí)現(xiàn)
wget http://labfile.oss.aliyuncs.com/courses/568/web_server.zip
一、C++ 基礎(chǔ)

面向?qū)ο蠛湍0迨?C++進(jìn)階知識(shí)的基礎(chǔ),這里不做過(guò)多介紹,本次項(xiàng)目我們將開(kāi)發(fā)一個(gè) Web 框架,我們?cè)谶@里先回顧一下命名空間、和 sstream 字符串 IO 流的相關(guān)知識(shí)。如果對(duì)這部分比較熟悉,可以直接跳過(guò)本小節(jié)。

命名空間

在開(kāi)發(fā)庫(kù)時(shí),庫(kù)通常會(huì)有定義大量的全局名稱,這時(shí)候當(dāng)我們使用的庫(kù)越來(lái)越多時(shí),就不可避免的發(fā)生名稱沖突的情況,這也就是我們常說(shuō)的命名空間污染。

在命名空間誕生以前,通常使用的辦法就是把一個(gè)函數(shù)、類、甚至變量名等名字取得足夠長(zhǎng),在每一個(gè)名字的前面都增加相應(yīng)的前綴,例如,當(dāng)我們只想要定義一個(gè) port 的變量時(shí)候:

// 原本的樣子
int port;
// 實(shí)際的樣子
int shiyanlou_web_server_port;
命名空間的定義非常簡(jiǎn)單,通過(guò)關(guān)鍵字 namespace 加上命名空間的名字,再使用花括號(hào)包裹需要的定義和聲明即可完成相關(guān)的定義,例如:

namespace shiyanlou_web_server {
int port = 0;
}
這時(shí),這個(gè) port 就被限制在了命名空間 shiyanlou_web_server 當(dāng)中,如果不通過(guò)命名空間的指定,就不會(huì)被訪問(wèn)到。

參考下面的例子:

//
// main.cpp
//
#include <iostream>
#include "web.hpp"
#include "web2.hpp"
int main() {
std::cout << "hello world!" << std::endl;
std::cout << "shiyanlou_web_server, port=" << shiyanlou_web_server::port << std::endl;
std::cout << "shiyanlou_web2_server, port=" << shiyanlou_web2_server::port << std::endl;
return 0;
}
//
// web.hpp
//
namespace shiyanlou_web_server{
int port = 0;
}
//
// web2.hpp
//
namespace shiyanlou_web2_server{
int port = 2;
}
最后的輸出結(jié)果為:

hello world!
shiyanlou_web_server, port=0
shiyanlou_web2_server, port=2
常用 IO 庫(kù)

我們常說(shuō)的 C++ IO 庫(kù)一般指 iostream, fstream, sstream。

iostream 包含了 istream(從流讀)/ostream(從流寫(xiě))/iostream(讀寫(xiě)流)
fstream 包含了 ifstream(從文件讀)/ofstream(condition 文件寫(xiě))/fstream(讀寫(xiě)文件)
sstream 包含了 istringstream(從 string 讀)/ostringstream(向 string 寫(xiě))/stringstream(讀寫(xiě) string)
其實(shí)標(biāo)準(zhǔn)庫(kù)還有寬字符版本,但我們這里不討論,有興趣的話可以參考參考鏈接。
iostream 和 fstream 是兩個(gè)比較常用的IO 庫(kù),我們這里不再回顧,這里簡(jiǎn)單回顧一下 sstream。

如果你熟悉 C 語(yǔ)言,就知道將 int 轉(zhuǎn)換為 string 類型其實(shí)是一件很麻煩的事情,雖然標(biāo)準(zhǔn)庫(kù)中提供了 itoa() 這種函數(shù),但是依然需要對(duì)轉(zhuǎn)換后的 C 風(fēng)格字符串(char *)通過(guò) std::string 的構(gòu)造函數(shù)構(gòu)造為 std::string。

如果使用流操作,那么這將變得異常的簡(jiǎn)單:

#include <string>
#include <sstream>
#include <iostream>

int main() {
// std::stringstream 支持讀寫(xiě)
std::stringstream stream;
std::string result;
int number = 12345;
stream << number; // 將 number 輸入到 stream
stream >> results; // 從 stream 讀取到 result
std::cout < result << std::endl; // 將輸出為字符串"12345"
}
如果希望讓sstream 和 C 風(fēng)格的字符串打交道,同樣也可以:

#include <sstream>
#include <iostream>

int main()
{
std::stringstream stream;
char result[6];
stream << 12345;
stream >> result;
std::cout << result << std::endl;
}
需要注意的一點(diǎn)就是,在進(jìn)行多次IO 操作時(shí),如果希望結(jié)果彼此不影響,需要對(duì) stream 對(duì)象進(jìn)行一次 clear() 操作:

stream.clear()
二、C++11 相關(guān)

C++11 幾乎重新定義了 C++ 的一切,C++11 的出現(xiàn)伴隨著大量的有用的新特性和標(biāo)準(zhǔn)庫(kù),這些特性和標(biāo)準(zhǔn)使得 C++ 變得更加現(xiàn)代,甚至在編碼范式上都與傳統(tǒng) C++ 有著本質(zhì)上的差異,本節(jié)我們將回顧一下這些特性:

lambda expression
std::shared_ptr
std::make_shared
std::unordered_map
std::regex
std::smatch
std::regex_match
std::function
std::thread
如果對(duì)這些特性比較熟悉,可以直接跳過(guò)本節(jié)。

lambda 表達(dá)式

Lambda 表達(dá)式是 C++11中最重要的新特性之一,而 Lambda 表達(dá)式,實(shí)際上就是提供了一個(gè)類似匿名函數(shù)的特性,而匿名函數(shù)則是在需

來(lái)源: 實(shí)驗(yàn)樓
鏈接: https://www.shiyanlou.com/courses/568
本課程內(nèi)容,由作者授權(quán)實(shí)驗(yàn)樓發(fā)布,未經(jīng)允許,禁止轉(zhuǎn)載、下載及非法傳播

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI