首先需要按照grpc官網上說的辦法從github上下載源碼,編譯,然后跑一跑對應的測試代碼。我分析的代碼版本為v1.20.0。
在cpp的helloworld例子中,client端,第一個函數是創建channel。
GreeterClient greeter(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
我們從這里開始分析,CreateChannel這個函數的具體實現在src/cpp/client/create_channel.cc(這個文件里指定了namespace grpc),CreateChannel再調用CreateCustomChannel,這里會根據creds的類型來創建Channel。
std::shared_ptr<Channel> CreateCustomChannel( const grpc::string& target, const std::shared_ptr<ChannelCredentials>& creds, const ChannelArguments& args) { GrpcLibraryCodegen init_lib; // We need to call init in case of a bad creds. return creds ? creds->CreateChannel(target, args) : CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), std::vector<std::unique_ptr< experimental::ClientInterceptorFactoryInterface>>()); }
creds的類型為ChannelCredentials,那我們來具體看看ChannelCredentials這個類是如何實現的,ChannelCredentials這個類的定義在include/grpcpp/security/credentials.h文件中,這里定義了虛函數CreateChannel。
virtual std::shared_ptr<Channel> CreateChannel( const grpc::string& target, const ChannelArguments& args) = 0;
以ChannelCredentials類為父類的子類有,InsecureChannelCredentialsImpl,CronetChannelCredentialsImpl,SecureChannelCredentials,具體是哪個類,我們需要再看下CreateChannel的第二個參數,
grpc::InsecureChannelCredentials()
InsecureChannelCredentials這個函數的定義和實現在src/cpp/client/insecure_credentials.cc文件中,函數中創建了一個指向ChannelCredentials類的InsecureChannelCredentialsImpl對象,再看InsecureChannelCredentialsImpl類實現的CreateChannel。也就是根據c++的多態用法,在上面提到的CreateCustomChannel函數中,調用的CreateChannel,就是調用InsecureChannelCredentialsImpl這個類的CreateChannel。
我們再來看一下CreateChannel的調用關系,CreateChannel->CreateChannelWithInterceptors->CreateChannelInternal,CreateChannelInternal其實就是創建了一個Channel對象,創建對象的參數中,有host信息,指向grpc_channel的指針,還有一個是ClientInterceptorFactoryInterface類指針的vector。這里我先重點關注下第二個參數,看其是如何生成的。在CreateChannelWithInterceptors函數中,使用grpc_insecure_channel_create這個函數來生成grpc_channel,下面來具體分下這個函數。
grpc_insecure_channel_create 這個函數是grpc core中提供的so接口,實現在ext/transport/chttp2/client/insecure/channel_create.cc這個文件中。
