我正在弄乱GRPC
。当前,我正在使用C#
Web应用程序作为GRPC
服务器,并且正在使用C++
控制台应用程序作为客户端。
我能够毫无问题地成功连接服务器并与之通信。问题出在我退出C++
控制台客户端应用程序。退出时会抛出Access Violation
。
堆栈跟踪
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body
MeterReaderClientCpp.exe!__acrt_lock
ntdll.dll!RtlpWaitOnCriticalSection()
ntdll.dll!RtlpEnterCriticalSectionContended()
ntdll.dll!RtlEnterCriticalSection()
MeterReaderClientCpp.exe!__acrt_lock(__acrt_lock_id _Lock) Line 55
MeterReaderClientCpp.exe!_free_dbg(void * block, int block_use) Line 1019
MeterReaderClientCpp.exe!free(void * block) Line 32
MeterReaderClientCpp.exe!gpr_free(void * p) Line 53
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::destroy_thread() Line 142
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::Join() Line 112
MeterReaderClientCpp.exe!grpc_core::Thread::Join() Line 147
MeterReaderClientCpp.exe!gc_completed_threads() Line 74
MeterReaderClientCpp.exe!stop_threads() Line 331
MeterReaderClientCpp.exe!grpc_timer_manager_set_threading(bool threaded) Line 351
MeterReaderClientCpp.exe!grpc_shutdown_internal_locked() Line 175
MeterReaderClientCpp.exe!grpc_shutdown_internal(void * __formal) Line 208
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body(void * v) Line 128
GRPC客户端
int main( )
{
using namespace MeterReaderWeb::Services;
using namespace google::protobuf::util;
using namespace google::protobuf;
std::cout << "Press enter\n";
std::cin.ignore( );
std::cout << "Calling Grpc service\n";
std::fstream file{ R"(C:\Certificates\certificate.cer)", std::ios::in | std::ios::beg };
if ( !file.is_open( ) )
{
std::cerr << "Failed to open file\n";
return 1;
}
std::stringstream buffer;
buffer << file.rdbuf( );
grpc::SslCredentialsOptions options;
options.pem_root_certs = buffer.str( );
auto credentials{ grpc::SslCredentials( options ) };
auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
auto stub{ MeterReadingService::NewStub( channel ) };
ReadingPacket packet;
packet.set_status( ReadingStatus::METER_READER_SUCCESS );
packet.set_notes( "Here are some random notes" );
auto message{ packet.add_readings( ) };
message->set_customer_id( 1 );
message->set_reading_value( 10001 );
auto timestamp{ message->mutable_reading_time( ) };
timestamp->CopyFrom( TimeUtil::GetCurrentTime( ) );
grpc::ClientContext context;
StatusMessage response;
if ( auto status{ stub->AddReading( &context, packet, &response ) }; status.ok( ) )
{
std::cout << "Added reading successfully\n";
auto responseStatus{ response.status( ) };
if ( responseStatus == ReadingStatus::METER_READER_SUCCESS )
{
std::cout << "Server status: success\n"
<< "Message: " << response.message( ) << '\n';
}
}
else
{
std::cerr << "Error: " << status.error_message( ) << '\n';
std::cerr << "Error Details: " << status.error_details( ) << '\n';
}
std::cin.ignore( );
}
[我大量使用GRPC
route_guide_client.cc
作为指导来帮助我编写上述应用程序。
我已经尝试将调用添加到grpc_init( )
和grpc_shutdown( )
,即使它们的客户端示例都不包含任何调用。但是添加这些没有效果。
我在这里想念什么(如果有的话?我是否忘了调用/填充框架在应用程序退出时试图清除的内容?
好的,我相信我已经找到了造成此问题的原因。
在我的原始帖子中,我说:
即使在
grpc_init( )
和grpc_shutdown( )
中,我都尝试添加了呼叫客户示例不包含任何调用。但添加这些无效。“
是的,但是在重新阅读了grpc_shutdown( )
的文档后,我注意到了这一点(强调我的意思:)>
最后一次调用
grpc_shutdown
将启动清理grpc库内部,可能发生在另一个线程中。一旦清理完成,grpc不使用任何内存,也没有任何指令在grpc库中执行。 在致电之前,所有申请拥有的grpc对象必须已销毁。这是我认为我做错了的地方。我仍然在作用域中有grpc对象时正在调用
grpc_shutdown()
。为了更正,我确定了grpcobjects
的范围,然后在退出该范围时调用了grpc_shutdown()
。这似乎已解决了问题。
New Grpc Client
int main( )
{
std::cout << "Press enter\n";
std::cin.ignore( );
std::cout << "Calling Grpc service\n";
grpc_init( );
{ // <- Intentionally added scope here.
grpc::SslCredentialsOptions options;
if ( auto certificate{ ReadCertificate( ) } )
options.pem_root_certs = std::move( certificate ).value( );
else return 1;
auto credentials{ grpc::SslCredentials( options ) };
auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
auto stub{ MeterReadingService::NewStub( channel ) };
std::cout << "Sending single packet\n";
SendPacket( stub.get( ), 8000 );
std::cout << "Sending multiple packets\n";
StreamDiagnostics( stub.get( ), 3 );
}
std::cout << "Shutting down library\n";
grpc_shutdown_blocking( );
std::cout << "Shut down complete press enter to exit\n";
std::cin.ignore( );
}