`
tcspecial
  • 浏览: 911913 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

基于http的protobuf服务实现

阅读更多

 

通常webapi实现通过http get/post请求,返回文本型的json,xml等字符串。本文以Tomcat8为web服务器,借助protobuf框架,响应二进制数据。

由于protobuf协议能跨语言,我们可以用java servlet实现服务端,C/C++实现客户端,达到各模块解耦目的。双方需设置ContentType为application/x-protobuf。

 

1. 准备proto文件

 

package qwd.kettas;

// 请求结构
message CTestReq
{
        optional uint32 ShopId = 1;   // 店铺ID
}

message CProduct
{
        optional uint32 Id = 1;      // 商品ID
        optional bytes Name = 2;     // 商品名称
        optional double price = 3;   // 商品价格
}

// 响应结构
message CTestResp
{
        optional int32 Total = 1;        // 商品总数
        repeated CProduct Product = 2;   // 商品数组
}

 

2. Java Servlet服务

 

/**
 * Servlet 服务实现,接收post请求,响应protocol buffer二进制数据
 */
protected void service( HttpServletRequest req, HttpServletResponse resp )
	throws ServletException, IOException {
	/*	
	 * 注:用in.read() 无数据部分填充0,会导致parseFrom()失败,不可行。
	byte[] postBuf = new byte[128];
	InputStream in = req.getInputStream();
	int len = in.read( postBuf );
	 */
	
	// protobuf 解析参数
	CTestReq tReq = CTestReq.parseFrom( req.getInputStream() );	// InputStream作为参数
	int shopid = tReq.getShopId();
	
	// 准备数据
	CTestResp.Builder pBuilder = CTestResp.newBuilder();
	pBuilder.setTotal(2);
	
	// 产品一
	CProduct.Builder pProBuild1 = CProduct.newBuilder();
	pProBuild1.setId( shopid + 1001 );
	pProBuild1.setName( ByteString.copyFrom("小明","UTF-8") );	// 字符串需要通过ByteString转化,最好定义string
	pProBuild1.setPrice(15.8);
	pBuilder.addProduct( pProBuild1 );
	
	// 产品二
	pProBuild1 = CProduct.newBuilder();
	pProBuild1.setId( shopid + 1002 );
	pProBuild1.setName( ByteString.copyFrom("小王","UTF-8") );
	pProBuild1.setPrice(29.8);
	pBuilder.addProduct( pProBuild1 );
	
	// reponse
	CTestResp pResp = pBuilder.build();
	System.out.println( "Data: " + pResp.toString() );
	
	// 序列化
	byte[] buff = pResp.toByteArray();
	
	// 响应,设置HTTP头部为: application/x-protobuf
	resp.setContentType("application/x-protobuf");
	resp.getOutputStream().write( buff );	// 发送
}

 

 

3. 客户端测试

 

// 数据回调函数
size_t OnWriteData( void* buffer, size_t size, size_t nmemb, void *lpVoid )
{
        std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
        if ( NULL == str || NULL == buffer )
        {   
                return -1; 
        }   

        char* pData = (char*)buffer;
        str->append(pData, size * nmemb);
        return nmemb;
}


// curl模拟post请求
void TestCurl()
{
        printf( "\n****************TestCurl*******************\n" );
        const char *url = "http://10.14.230.7:8080/protoweb/proto";
        CTestReq req;
        CTestResp resp;
        string sReq;
        string sResp;

        req.set_shopid( 1500 );

        // 序列化请求
        if ( !req.SerializeToString(&sReq) )
                return;

        curl_slist *m_header = NULL;
        m_header = curl_slist_append( m_header, "Content-Type: application/x-protobuf" );  // 设置消息头

        CURL *curl = curl_easy_init();
        curl_easy_setopt( curl, CURLOPT_HTTPHEADER, m_header ); // Header
        curl_easy_setopt( curl, CURLOPT_REFERER, "nginx" );
        curl_easy_setopt( curl, CURLOPT_VERBOSE, 1L );
        curl_easy_setopt( curl, CURLOPT_URL, url );
        curl_easy_setopt( curl, CURLOPT_NOSIGNAL, 1);
                                          
        curl_easy_setopt( curl, CURLOPT_POSTFIELDS, sReq.c_str() );             // Post
        curl_easy_setopt( curl, CURLOPT_POSTFIELDSIZE, sReq.length() );
        curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, OnWriteData );
        curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void*)&sResp );     // Accept data

        CURLcode ret = curl_easy_perform( curl );
        assert( ret == CURLE_OK );
        curl_easy_cleanup( curl );
        curl_slist_free_all( m_header );

        // 反序列化数据
        if ( !resp.ParseFromString(sResp) )
                return;

        printf( "Response: %s\n", resp.DebugString().c_str() );
}

 

执行结果,curl发起post请求,返回46字节内容:

 

http client 

 

 

  • 大小: 33.7 KB
分享到:
评论

相关推荐

    基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip

    基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip基于C++ module库 Protobuf Zookeeper 实现的Rpc框架.zip基于C++ module库 Protobuf Zookeeper 实现...

    nanopb 基于嵌入式protobuf的移植例程

    2. **nanopb简介**:`nanopb`由Jesse Tuomela开发,主要针对嵌入式系统,提供了一个轻量级的protobuf实现。它不依赖动态内存分配,且支持代码生成,使得开发者能够轻松地将protobuf消息集成到C代码中。 3. **移植...

    Unity3D 与 Java 基于 Protobuf 通信实现(客户端)

    本教程将深入探讨如何利用Protocol Buffers(Protobuf)在Unity3D客户端与Java服务器之间实现通信。Protocol Buffers是一种高效的数据序列化协议,由Google开发,它能够将结构化数据转化为二进制格式,便于网络传输...

    基于netty和protobuf的聊天系统,客户端+服务器

    这个项目“基于netty和protobuf的聊天系统,客户端+服务器”就是这样一个实例,它展示了如何利用Java语言结合Netty框架和Protocol Buffers(protobuf)来搭建一个高性能、低延迟的聊天应用。 Netty是一个开源的异步...

    netty http protobuf

    Netty、HTTP与Protobuf是三个在IT领域中至关重要的技术组件,它们分别在不同的层面上为高...通过Netty实现HTTP服务器和客户端,利用Protobuf进行高效的数据序列化和反序列化,可以极大地提升应用程序的性能和可扩展性。

    protobuf实例-C#-聊天服务器

    总之,这个“protobuf实例-C#-聊天服务器”项目提供了一个使用protobuf进行网络通信的示例,展示了如何在C#中利用protobuf实现高效的序列化和反序列化,以及如何构建简单的聊天服务器。通过对该项目的研究和学习,...

    rust 基于 tokio protobuf tls websocket demo 版 chat server

    rust 基于tokio-websockets actor tls demo chat server(websocket) 聊天服务器,全异步实现,使用protobuf协议,所属分类 后端没有rust 这里只好下载c++

    基于C++实现使用protobuf完成网络通信源码.zip

    基于C++实现使用protobuf完成网络通信源码.zip基于C++实现使用protobuf完成网络通信源码.zip基于C++实现使用protobuf完成网络通信源码.zip基于C++实现使用protobuf完成网络通信源码.zip基于C++实现使用protobuf完成...

    一个基于Nacos、Netty、Protobuf 实现的简单易懂的RCP框架.zip

    开发者可以克隆或下载这个仓库,然后在本地环境中编译和运行项目,以了解和学习如何利用Nacos、Netty和Protobuf实现RPC框架。 这个框架的实现对于学习分布式系统、网络编程以及序列化技术非常有帮助。开发者可以...

    Android中基于protobuf的socket通信的实例

    总之,基于protobuf的socket通信在Android中能够提供高效、简洁的数据交换方式。通过protobuf定义数据结构,使用socket进行网络通信,可以构建稳定可靠的Android应用与服务器之间的通信桥梁。在实际项目中,你可以...

    基于netty与protobuf的Android手机视频实时传输

    本项目“基于Netty与Protobuf的Android手机视频实时传输”利用了高性能的网络库Netty和高效的序列化框架Protobuf,实现了高效、低延迟的视频流传输。下面将详细介绍这两个关键技术及其在该项目中的应用。 **Netty**...

    实现protobuf与json的互转

    通过反射机制,可以基于Descriptor在运行时处理protobuf消息,实现protobuf与JSON的动态转换。 7. **protobuf的兼容性**:protobuf支持版本兼容性,这意味着新版本的protobuf编译器可以解析旧版本的.proto文件,这...

    基于C++ module库 Protobuf Zookeeper实现的Rpc框架源码+项目说明.zip

    基于C++ module库 Protobuf Zookeeper实现的Rpc框架源码+项目说明.zip 编译: `./autobuild.sh` 运行 bin目录下: `./provider -i test.conf ` (启动Rpc提供者) `./consumer -i test.conf`(启动Rpc调用者) ...

    基于protobuf和gRPC的消息订阅服务器和客户端.zip

    在本项目"基于protobuf和gRPC的消息订阅服务器和客户端"中,我们将探讨如何使用Python来实现一个这样的系统,它允许客户端订阅并接收来自服务器的消息。 protobuf(Protocol Buffers)是一种数据序列化协议,它可以...

    netty基于protobuf的简单示例

    在服务端,我们需要实现一个 Netty 服务器,它接收客户端的请求,解码 protobuf 消息,处理业务逻辑,然后编码回消息给客户端。Netty 中的 `ChannelHandlerContext` 和 `ByteToMessageDecoder`、`...

    基于C++,Protobuf实现,以Zookeeper为服务配置中心的分布式RPC通信框架.zip

    基于C++,Protobuf实现,以Zookeeper为服务配置中心的分布式RPC通信框架 C++是一种广泛使用的编程语言,它是由Bjarne Stroustrup于1979年在新泽西州美利山贝尔实验室开始设计开发的。C++是C语言的扩展,旨在...

    基于protobuf-net的C# Protobuf 插件.zip

    总结起来,这个压缩包提供了一个基于protobuf-net的C#实现,用于数据序列化和反序列化。它对C#开发者尤其有用,同时涉及到C++的背景知识,适合学习者在毕业设计或课程设计中使用,提升跨语言通信和数据交换的技能。...

    游戏服务器消息协议Protobuf

    对于C#开发者,他们可以使用`Google.Protobuf.dll`库来实现数据序列化和反序列化;而对于Python开发者,他们将依赖于对应的Python包,如`protobuf`,来实现相同的功能。 使用Protobuf的优势在于其高效性和跨平台性...

Global site tag (gtag.js) - Google Analytics