最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++編寫高性能服務(wù)器實(shí)例教程

 更新時(shí)間:2020年06月01日 14:52:45   作者:慕神8447489  
這篇文章主要介紹了如何用C++編寫高性能服務(wù)器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)C++有一定的參考價(jià)值,需要的朋友們可以了解下

我將展示如何使用現(xiàn)代C++編寫一個(gè)Echo服務(wù)器,相當(dāng)于分布式系統(tǒng)開(kāi)發(fā)中的“Hello World”。這個(gè)服務(wù)器會(huì)將接收的消息直接返回。我們同時(shí)需要一個(gè)可以向我們的服務(wù)器發(fā)動(dòng)消息的客戶端,在這里可以發(fā)現(xiàn)客戶端的源碼。

Wangle是一個(gè)用來(lái)搭建事件驅(qū)動(dòng)的現(xiàn)代異步C++服務(wù)的C/S應(yīng)用框架。Wangle最基本的抽象概念就是Pipeline(管線)。能夠理解這種抽象,將會(huì)很容易寫出各種復(fù)雜的現(xiàn)代C++服務(wù),另一個(gè)重要的概念是Service(服務(wù)),其可以看作一種更高級(jí)的Pipeline,不過(guò)超出了本文我們關(guān)注的范疇。

PipeLine

pipeline 是 Wangle 中最重要也是最強(qiáng)大的抽象,可以讓用戶在定制 request 和 response 的實(shí)現(xiàn)時(shí)擁有很大的自由。一個(gè)pipeline就是一系列request/response控制程序的嵌套。我試圖尋找一個(gè)真實(shí)世界中pipeline的類比,唯一我能想到的就是現(xiàn)實(shí)世界工廠中的生產(chǎn)線。一條生產(chǎn)線工作在一種順序模式下,所有的工人取得一個(gè)物體,并且只添加一種修改,再將其發(fā)送給上游的工人直到整個(gè)產(chǎn)品制造完成。這可能不是一個(gè)特別好的比喻,因?yàn)榱魉€上產(chǎn)品的流動(dòng)是單向的,而一個(gè)pipeline能控制反方向的數(shù)據(jù)流動(dòng)--就好像將成品分解成原材料。

一個(gè)Wangle handler可以同時(shí)掌控上游和下游的兩個(gè)方向的數(shù)據(jù)流動(dòng)。當(dāng)你把所有的handler連接在一起,就可以用一種靈活的方式將原始數(shù)據(jù)組裝為想要的數(shù)據(jù)類型或者將已有的數(shù)據(jù)拆分。

在我們的服務(wù)器的pipeline中大致將會(huì)有下面幾種handler:

1.Handler 1 (下文的上游下游是指對(duì)一同個(gè)handler而言,根據(jù)其在pipeline中的位置不同,輸入輸出相反) 上游:將從socket中接收的二進(jìn)制數(shù)據(jù)流寫入一個(gè)零拷貝(zero-copy,指省略了Applicaion context和Kernel context之間的上下文切換,避免了CPU對(duì)Buffer的冗余拷貝,直接在Kernel級(jí)別進(jìn)行數(shù)據(jù)傳輸?shù)募夹g(shù),詳情請(qǐng)參閱維基百科)的字節(jié)緩存中,發(fā)送給handler2

下游:接收一個(gè)零拷貝的字節(jié)緩存,將其內(nèi)容寫入socket中

2.Handler2 上游:接收handler1的緩存對(duì)象,解碼為一個(gè)string對(duì)象傳遞給handler3 下游:接收handler3的string對(duì)象,將其轉(zhuǎn)碼為一個(gè)零拷貝的字節(jié)緩存,發(fā)送給handler1

3.Handler3 上游:接收handler2中的string對(duì)象,再向下發(fā)送至pipeline等待寫回客戶端。string會(huì)發(fā)回handler2 下游:接收上游的string對(duì)象,傳遞給handler2

需要注意的一點(diǎn)是,每一個(gè)handler應(yīng)當(dāng)只做一件事并且只有一件,如果你有一個(gè)handler里做了多項(xiàng)任務(wù),比如從二進(jìn)制流離直接解碼出string,那么你需要學(xué)會(huì)將它拆分。這對(duì)提升代碼的可維護(hù)性和擴(kuò)展性非常重要。

另外,沒(méi)錯(cuò),handler不是線程安全的,所以不要輕易的在其中使用任何沒(méi)有經(jīng)過(guò)mutex,atomic lock保護(hù)的數(shù)據(jù),如果你確實(shí)需要一個(gè)線程安全的環(huán)境,F(xiàn)olly提供了一種免于加鎖的數(shù)據(jù)結(jié)構(gòu), Folly依賴于Wangle,你可以很容易的在項(xiàng)目中引入并使用它。

如果你還不是很明白所有的步驟,不用著急,在看到下面的具體實(shí)現(xiàn)時(shí)你會(huì)更加清楚。

Echo Server

下面我會(huì)展示服務(wù)器的具體實(shí)現(xiàn)。我假定您已經(jīng)安裝好Wangle。需要注意的是截至目前Wangle還不能在Mac OS上安裝,我建議您可以安裝虛擬機(jī),使用Ubuntu來(lái)安裝Wangle。

這就是echo handler:接收一個(gè)string,打印到stdout中,再發(fā)送回pipeline。要注意write語(yǔ)句中的定界符不可以省略,因?yàn)閜ipeline會(huì)按照字節(jié)解碼。

// the main logic of our echo server; receives a string and writes it straight

// back

class EchoHandler : public HandlerAdapter {

public:

 virtual void read(Context* ctx, std::string msg) override {

 std::cout << "handling " << msg << std::endl;

 write(ctx, msg + "rn");

 }

};

Echohandler其實(shí)是我們pipeline的最后一個(gè)handler,現(xiàn)在我們需要?jiǎng)?chuàng)建一個(gè)PipelineFactory來(lái)控制所有的request和response。

// where we define the chain of handlers for each messeage received

class EchoPipelineFactory : public PipelineFactory {

public:

 EchoPipeline::Ptr newPipeline(std::shared_ptr sock) {

 auto pipeline = EchoPipeline::create();

 pipeline->addBack(AsyncSocketHandler(sock));

 pipeline->addBack(LineBasedFrameDecoder(8192));

 pipeline->addBack(StringCodec());

 pipeline->addBack(EchoHandler());

 pipeline->finalize();

 return pipeline;

 }

};

pipeline中每一個(gè)handler的插入順序都需要嚴(yán)格注意,因?yàn)樗鼈兪前凑障群笈判虻?,此處我們?個(gè)handler

1.AsyncSocketHandler: 上游:讀取scoket中的二進(jìn)制流轉(zhuǎn)換成零拷貝字節(jié)緩存 下游:將字節(jié)緩存內(nèi)容寫入底層socket

2. LineBasedFrameDecoder: 上游:接收字節(jié)緩存,按行分割數(shù)據(jù) 下游:將字節(jié)緩存發(fā)送給AsyncSocketHandler

3. StringCodec: 上游:接收字節(jié)緩存,解碼為std:string傳遞給EchoHandler 下游:接收std:string, 編碼為字節(jié)緩存,傳遞給LineBasedFrameDecoder

4. EchoHandler: 上游:接收std:string對(duì)象,將其寫入pipeline-將消息返回給Echohandler。 下游:接收一個(gè)std:string對(duì)象,轉(zhuǎn)發(fā)給StringCodec Handler。 現(xiàn)在我們所需要做的就是將pipeline factory關(guān)聯(lián)到ServerBootstrap,綁定一個(gè)端口,這樣我們已經(jīng)完成了 基本上所有的工作。

#include <gflags/gflags.h>



#include <wangle/bootstrap/ServerBootstrap.h>

#include <wangle/channel/AsyncSocketHandler.h>

#include <wangle/codec/LineBasedFrameDecoder.h>

#include <wangle/codec/StringCodec.h>



using namespace folly;

using namespace wangle;



DEFINE_int32(port, 8080, "echo server port");



typedef Pipeline<IOBufQueue&, std::string> EchoPipeline;



// the main logic of our echo server; receives a string and writes it straight

// back

class EchoHandler : public HandlerAdapter<std::string> {

public:

 virtual void read(Context* ctx, std::string msg) override {

 std::cout << "handling " << msg << std::endl;

 write(ctx, msg + "\r\n");

 }

};



// where we define the chain of handlers for each messeage received

class EchoPipelineFactory : public PipelineFactory<EchoPipeline> {

public:

 EchoPipeline::Ptr newPipeline(std::shared_ptr<AsyncTransportWrapper> sock) {

 auto pipeline = EchoPipeline::create();

 pipeline->addBack(AsyncSocketHandler(sock));

 pipeline->addBack(LineBasedFrameDecoder(8192));

 pipeline->addBack(StringCodec());

 pipeline->addBack(EchoHandler());

 pipeline->finalize();

 return pipeline;

 }

};



int main(int argc, char** argv) {

 google::ParseCommandLineFlags(&argc, &argv, true);



 ServerBootstrap<EchoPipeline> server;

 server.childPipeline(std::make_shared<EchoPipelineFactory>());

 server.bind(FLAGS_port);

 server.waitForStop();



 return 0;

}

至此我們一共只寫了48行代碼就完成了一個(gè)高性能的異步C++服務(wù)器。

Echo Client

echo客戶端的實(shí)現(xiàn)與我們的服務(wù)端非常類似:

// the handler for receiving messages back from the server

class EchoHandler : public HandlerAdapter {

public:

 virtual void read(Context* ctx, std::string msg) override {

 std::cout << "received back: " << msg;

 }

 virtual void readException(Context* ctx, exception_wrapper e) override {

 std::cout << exceptionStr(e) << std::endl;

 close(ctx);

 }

 virtual void readEOF(Context* ctx) override {

 std::cout << "EOF received :(" << std::endl;

 close(ctx);

 }

};

注意我們重載了readException和readEOF兩個(gè)方法,還有其他一些方法可以被重載。如果你需要控制某個(gè)特別的事件,只需要重載對(duì)應(yīng)的虛函數(shù)即可。

這是客戶端的pipeline factory的實(shí)現(xiàn),與我們的服務(wù)端結(jié)構(gòu)基本一致,只有EventBaseHandler這個(gè)handler在服務(wù)端代碼中不曾出現(xiàn),它可以確保我們可以從任意一個(gè)線程寫入數(shù)據(jù)。

// the handler for receiving messages back from the server

class EchoHandler : public HandlerAdapter {

public:

 virtual void read(Context* ctx, std::string msg) override {

 std::cout << "received back: " << msg;

 }

 virtual void readException(Context* ctx, exception_wrapper e) override {

 std::cout << exceptionStr(e) << std::endl;

 close(ctx);

 }

 virtual void readEOF(Context* ctx) override {

 std::cout << "EOF received :(" << std::endl;

 close(ctx);

 }

};

客戶端所有的代碼如下圖所示

#include <gflags/gflags.h>

#include



#include <wangle/bootstrap/ClientBootstrap.h>

#include <wangle/channel/AsyncSocketHandler.h>

#include <wangle/channel/EventBaseHandler.h>

#include <wangle/codec/LineBasedFrameDecoder.h>

#include <wangle/codec/StringCodec.h>



using namespace folly;

using namespace wangle;



DEFINE_int32(port, 8080, "echo server port");

DEFINE_string(host, "::1", "echo server address");



typedef Pipeline<folly::IOBufQueue&amp;, std::string> EchoPipeline;



// the handler for receiving messages back from the server

class EchoHandler : public HandlerAdapter {

public:

 virtual void read(Context* ctx, std::string msg) override {

 std::cout << "received back: " << msg;

 }

 virtual void readException(Context* ctx, exception_wrapper e) override {

 std::cout << exceptionStr(e) << std::endl;

 close(ctx);

 }

 virtual void readEOF(Context* ctx) override {

 std::cout << "EOF received :(" << std::endl;

 close(ctx);

 }

};



// chains the handlers together to define the response pipeline

class EchoPipelineFactory : public PipelineFactory {

public:

 EchoPipeline::Ptr newPipeline(std::shared_ptr sock) {

 auto pipeline = EchoPipeline::create();

 pipeline->addBack(AsyncSocketHandler(sock));

 pipeline->addBack(

 EventBaseHandler()); // ensure we can write from any thread

 pipeline->addBack(LineBasedFrameDecoder(8192, false));

 pipeline->addBack(StringCodec());

 pipeline->addBack(EchoHandler());

 pipeline->finalize();

 return pipeline;

 }

};



int main(int argc, char** argv) {

 google::ParseCommandLineFlags(&amp;argc, &amp;argv, true);



 ClientBootstrap client;

 client.group(std::make_shared(1));

 client.pipelineFactory(std::make_shared());

 auto pipeline = client.connect(SocketAddress(FLAGS_host, FLAGS_port)).get();



 try {

 while (true) {

 std::string line;

 std::getline(std::cin, line);

 if (line == "") {

 break;

 }



 pipeline->write(line + "rn").get();

 if (line == "bye") {

 pipeline->close();

 break;

 }

 }

 } catch (const std::exception&amp; e) {

 std::cout << exceptionStr(e) << std::endl;

 }



 return 0;

}

程序用一個(gè)While循環(huán)不斷監(jiān)測(cè)用戶的輸入,并且依靠調(diào)用.get() 來(lái)同步等待一直到請(qǐng)求被響應(yīng)。

以上就是C++編寫高性能服務(wù)器實(shí)例教程的詳細(xì)內(nèi)容,更多關(guān)于C++高性能服務(wù)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++中vector類的一些簡(jiǎn)單實(shí)現(xiàn)

    C++中vector類的一些簡(jiǎn)單實(shí)現(xiàn)

    C++中的std::vector是一個(gè)動(dòng)態(tài)數(shù)組(也被稱為可變大小數(shù)組)的容器類,它是C++標(biāo)準(zhǔn)庫(kù)提供的其中一種容器類,提供了方便的操作和管理動(dòng)態(tài)數(shù)組的功能,本文就給大家介紹了C++中vector類的簡(jiǎn)單實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2023-08-08
  • C++ 位圖及位圖的實(shí)現(xiàn)原理

    C++ 位圖及位圖的實(shí)現(xiàn)原理

    位圖實(shí)際上就是一個(gè)數(shù)組,因?yàn)閿?shù)組有隨機(jī)訪問(wèn)的功能,比較方便查找,這個(gè)數(shù)組一般是整形,今天通過(guò)本文給大家分享c++位圖的實(shí)現(xiàn)原理及實(shí)現(xiàn)代碼,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • 在C語(yǔ)言中g(shù)etchar的使用方法和讀取規(guī)則講解

    在C語(yǔ)言中g(shù)etchar的使用方法和讀取規(guī)則講解

    getchar中文意思是獲取字符,getchar函數(shù)從標(biāo)準(zhǔn)輸入輸出里讀取下一個(gè)字符,返回類型為int整形,返回用戶輸入的ASCII碼值,如果到達(dá)文件末尾或者出錯(cuò)返回EOF,這篇文章主要介紹了在C語(yǔ)言中g(shù)etchar的使用方法和讀取規(guī)則,需要的朋友可以參考下
    2022-12-12
  • C++ OpenCV實(shí)戰(zhàn)之圖像透視矯正

    C++ OpenCV實(shí)戰(zhàn)之圖像透視矯正

    這篇文章主要介紹了通過(guò)C++ OpenCV實(shí)現(xiàn)圖像的透視矯正,文中的示例代碼講解詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的可以了解一下
    2022-01-01
  • C++強(qiáng)制類型轉(zhuǎn)換(static_cast、dynamic_cast、const_cast、reinterpret_cast)

    C++強(qiáng)制類型轉(zhuǎn)換(static_cast、dynamic_cast、const_cast、reinterpret_ca

    本文主要介紹了C++強(qiáng)制類型轉(zhuǎn)換,主要介紹了static_cast、dynamic_cast、const_cast、reinterpret_cast的4種方法,感興趣的可以了解一下
    2021-08-08
  • C++ 情懷游戲掃雷的實(shí)現(xiàn)流程詳解

    C++ 情懷游戲掃雷的實(shí)現(xiàn)流程詳解

    掃雷是電腦上很經(jīng)典很經(jīng)典的傳統(tǒng)老游戲,從小編第一次摸到計(jì)算機(jī)開(kāi)始就玩過(guò)掃雷,雖然當(dāng)時(shí)并不理解玩法原理,但終是第一次玩電腦游戲,下面來(lái)從掃雷的前世今生講起
    2021-11-11
  • C語(yǔ)言分治法實(shí)現(xiàn)歸并排序

    C語(yǔ)言分治法實(shí)現(xiàn)歸并排序

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)歸并排序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • C++實(shí)現(xiàn)獲取本機(jī)MAC地址與IP地址

    C++實(shí)現(xiàn)獲取本機(jī)MAC地址與IP地址

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)獲取本機(jī)MAC地址與IP地址的兩種方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • 一篇文章帶你了解C語(yǔ)言函數(shù)遞歸

    一篇文章帶你了解C語(yǔ)言函數(shù)遞歸

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言函數(shù)遞歸,使用數(shù)據(jù)庫(kù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C語(yǔ)言必背的一些經(jīng)典程序代碼實(shí)例

    C語(yǔ)言必背的一些經(jīng)典程序代碼實(shí)例

    C語(yǔ)言是一種高級(jí)編程語(yǔ)言,具有很多優(yōu)點(diǎn),下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言必背的一些經(jīng)典程序代碼,文中通過(guò)詳細(xì)的實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05

最新評(píng)論

太谷县| 东至县| 东港市| 三门峡市| 临湘市| 庆安县| 渝中区| 星子县| 库尔勒市| 醴陵市| 漠河县| 若羌县| 巴塘县| 女性| 石门县| 晋城| 兰溪市| 富宁县| 虎林市| 米易县| 南华县| 澎湖县| 上虞市| 永和县| 称多县| 林口县| 扶风县| 安多县| 织金县| 府谷县| 威海市| 岑巩县| 陆河县| 栾川县| 喀喇沁旗| 孝义市| 中宁县| 大邑县| 新民市| 千阳县| 平泉县|