C++编写高性能服务器实例教程

2020-06-01 18:00:51王振洲

至此我们一共只写了48行代码就完成了一个高性能的异步C++服务器。

Echo Client

echo客户端的实现与我们的服务端非常类似:

// 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两个方法,还有其他一些方法可以被重载。如果你需要控制某个特别的事件,只需要重载对应的虚函数即可。

这是客户端的pipeline factory的实现,与我们的服务端结构基本一致,只有EventBaseHandler这个handler在服务端代码中不曾出现,它可以确保我们可以从任意一个线程写入数据。

// 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;

}