默认
打赏 发表评论 1
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
一个基于Protocol Buffer的Java代码演示
阅读(54399) | 评论(1 收藏2 淘帖1 1
微信扫一扫关注!

点评


Protocol Buffer就是一套数据交互协议,用在即时通讯/IM里的目的就是让通信流量变小。据说,腾讯手Q的编解码协议都已改为Protocol Buffer实现。

(移动端即时通讯/IM 学习和讨论QQ群:http://www.52im.net/portal.php?mod=topic&topicid=2

Protocol Buffer介绍


按照官网的描述:Protocol Buffer是Google提供的一个开源序列化框架。主要应用于通信协议,数据存储中的结构化数据的序列化。它类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。

虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持Java、C++、Python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。

Protocol Buffer的优势


1、语言中立;
2、平台中立;
3、高效性。

Protocol Buffer入门(Eclipse下Java环境的搭建)

更多案例请查阅源代码包protobuf-2.3.0.zip里面有关于各种支持语言(java,C++,python等 )的案例。


1、下载jar包 protobuf-java-2.3.0.jar

2、下载编译器protoc.exe

3、新建java工程test_protobuf;

4、导入protobuf-java-2.3.0.jar包

5、导入编译器protoc.exe到项目下

6、在项目下建存放文件.proto的文件夹proto

7、编写message并放在proto文件夹下,在这里我引用官网的例子,创建addressbook.proto代码如下:

package  tutorial;  
option java_package = "com.example.tutorial" ;  
option java_outer_classname = "AddressBookProtos" ;  
message Person {  
  required string name = 1 ;  
  required int32 id = 2 ;         // Unique ID number for this person.   
  optional string email = 3 ;  
  enum  PhoneType {  
    MOBILE = 0 ;  
    HOME = 1 ;  
    WORK = 2 ;  
  }  
  message PhoneNumber {  
    required string number = 1 ;  
    optional PhoneType type = 2  [ default  = HOME];  
  }  
  repeated PhoneNumber phone = 4 ;  
}  
// Our address book file is just one of these.   
message AddressBook {  
  repeated Person person = 1 ;  
}

有关编写规范和说明请参考官网文档。


8、编译addressbook.proto成指定的java类:

    命令行下进入编译器所在目录,执行如下命令

     > protoc -I=proto/ --java_out=src proto/addressbook.proto

其中,src为生成的java类的目标位置,这里我们选择项目的默认包,proto/addressbook.proto表示我们的proto文件,运行 后即生成java类,生成的java类被放在了package com.example.tutorial中。刚才我们指定的目标位置是src,为什么现在却被放在了这个包中呢?这和我们的 addressbook.proto文件中的option java_package = "com.example.tutorial";有关。欲了解更多,参考上节提到的官方文档。


9、现在有了生成的AddressBookProtos.java类,我们可以向文件里写入消息了,首先编写AddPerson.java,代码如下:

import  com.example.tutorial.AddressBookProtos.AddressBook;  
import  com.example.tutorial.AddressBookProtos.Person;   
import  java.io.BufferedReader;  
import  java.io.FileInputStream;  
import  java.io.FileNotFoundException;  
import  java.io.FileOutputStream;   
import  java.io.InputStreamReader;    
import  java.io.IOException;    
import  java.io.PrintStream;      
class  AddPerson{      
    // This function fills in a Person message based on user input.       
    static  Person PromptForAddress(BufferedReader stdin,PrintStream stdout) throws  IOException{        
        Person.Builder person = Person.newBuilder();  
        stdout.print("Enter person ID: " );        
        person.setId(Integer.valueOf(stdin.readLine()));          
        stdout.print("Enter name: " );        
        person.setName(stdin.readLine());          
        stdout.print("Enter email address (blank for none): " );        
        String email = stdin.readLine();        
        if  (email.length() >  0 ){          
            person.setEmail(email);       
        }         
        while  ( true ){          
            stdout.print("Enter a phone number (or leave blank to finish): " );  
            String number = stdin.readLine();          
            if  (number.length() ==  0 ){            
                break ;          
            }            
            Person.PhoneNumber.Builder phoneNumber = Person.PhoneNumber.newBuilder().setNumber(number);  
            stdout.print("Is this a mobile, home, or work phone? " );          
            String type = stdin.readLine();          
            if  (type.equals( "mobile" )){            
                phoneNumber.setType(Person.PhoneType.MOBILE);      
            } else   if  (type.equals( "home" )) {            
                phoneNumber.setType(Person.PhoneType.HOME);          
            } else   if  (type.equals( "work" )) {           
                phoneNumber.setType(Person.PhoneType.WORK);          
            } else  {            
                stdout.println("Unknown phone type.  Using default." );          
            }            
            person.addPhone(phoneNumber);        
        }          
        return  person.build();      
    }        
    // Main function: Reads the entire address book from a file,  adds one person based on user input,    
    //then writes it back out to the same file.       
    public   static   void  main(String[] args)  throws  Exception{        
        if  (args.length !=  1 ) {          
            System.err.println("Usage:  AddPerson ADDRESS_BOOK_FILE" );          
            System.exit(-1 );        
        }          
        AddressBook.Builder addressBook = AddressBook.newBuilder();          
        // Read the existing address book.         
        try  {          
            addressBook.mergeFrom(new  FileInputStream(args[ 0 ]));        
        } catch  (FileNotFoundException e) {          
            System.out.println(args[0 ] +  ": File not found.  Creating a new file." );        
        }          
        // Add an address.         
        addressBook.addPerson(          
            PromptForAddress(new  BufferedReader( new  InputStreamReader(System.in)), System.out));          
        // Write the new address book back to disk.         
        FileOutputStream output = new  FileOutputStream(args[ 0 ]);        
        addressBook.build().writeTo(output);       
        output.close();      
    }   
}  

首先配置参数,也就是消息被序列化后存储的文件名,这里,我们就把参数设置成AddressBook.代码中提到,运行时如果文件不存在,将会创建文件并写入;如果存在,就写入。运行程序,按照提示输入消息。然后查看我们的项目路径下,将会产生AddressBook文件。


10、上一步是将消息序列化到文件中,这一步将文件中的消息反序列化,类似地,我们创建一个类ListPeople.java 代码如下:

import  com.example.tutorial.AddressBookProtos.AddressBook;  
import  com.example.tutorial.AddressBookProtos.Person;  
import  java.io.FileInputStream;        
    public   class  ListPeople {      
        // Iterates though all people in the AddressBook and prints info about them.       
        static   void  Print(AddressBook addressBook) {        
            for  (Person person: addressBook.getPersonList()) {          
                System.out.println("Person ID: "  + person.getId());          
                System.out.println("  Name: "  + person.getName());          
                if  (person.hasEmail()) {            
                    System.out.println("  E-mail address: "  + person.getEmail());          
                }            
                for  (Person.PhoneNumber phoneNumber : person.getPhoneList()) {            
                    switch  (phoneNumber.getType()) {              
                        case  MOBILE:                
                            System.out.print("  Mobile phone #: " );                
                            break ;              
                        case  HOME:                
                            System.out.print("  Home phone #: " );                
                            break ;              
                        case  WORK:                
                            System.out.print("  Work phone #: " );                
                        break ;            
                    }            
                    System.out.println(phoneNumber.getNumber());          
                }        
            }      
        }        
        // Main function:  Reads the entire address book from a file and prints all  the information inside.       
        /**  
         * @param args  
         * @throws Exception  
         */   
        public   static   void  main(String[] args)  throws  Exception {        
            if  (args.length !=  1 ) {          
                System.err.println("Usage:  ListPeople ADDRESS_BOOK_FILE" );          
                System.exit(-1 );        
            }          
            // Read the existing address book.         
            AddressBook addressBook = AddressBook.parseFrom(new  FileInputStream(args[ 0 ]));  
            Print(addressBook);      
        }    
}  

运行程序,将会看到我们输入的消息体被遍历并打印出来了!

通过一个简单的例子,希望能够对大家有所帮助!


(原文链接:http://blog.csdn.net/crzy_sparrow/article/details/6278563

全站即时通讯技术资料分类


[1] 网络编程基础资料:
TCP/IP详解 - 第11章·UDP:用户数据报协议
TCP/IP详解 - 第17章·TCP:传输控制协议
TCP/IP详解 - 第18章·TCP连接的建立与终止
TCP/IP详解 - 第21章·TCP的超时与重传
理论经典:TCP协议的3次握手与4次挥手过程详解
理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程
计算机网络通讯协议关系图(中文珍藏版)
NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等
UDP中一个包的大小最大能多大?
Java新一代网络编程模型AIO原理及Linux系统AIO介绍
NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战
NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
>> 更多同类文章 ……

[2] 有关IM/推送的通信格式、协议的选择:
为什么QQ用的是UDP协议而不是TCP协议?
移动端即时通讯协议选择:UDP还是TCP?
如何选择即时通讯应用的数据传输格式
强列建议将Protobuf作为你的即时通讯应用数据传输格式
移动端IM开发需要面对的技术问题(含通信协议选择)
简述移动端IM开发的那些坑:架构设计、通信协议和客户端
理论联系实际:一套典型的IM通信协议设计详解
58到家实时消息系统的协议设计等技术实践分享
>> 更多同类文章 ……

[3] 有关IM/推送的心跳保活处理:
Android进程保活详解:一篇文章解决你的所有疑问
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
为何基于TCP协议的移动端IM仍然需要心跳保活机制?
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
移动端IM实践:实现Android版微信的智能心跳机制
移动端IM实践:WhatsApp、Line、微信的心跳策略分析
>> 更多同类文章 ……

[4] 有关WEB端即时通讯开发:
新手入门贴:史上最全Web端即时通讯技术原理详解
Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE
SSE技术详解:一种全新的HTML5服务器推送事件技术
Comet技术详解:基于HTTP长连接的Web端实时通信技术
WebSocket详解(一):初步认识WebSocket技术
socket.io实现消息推送的一点实践及思路
>> 更多同类文章 ……

[5] 有关IM架构设计:
浅谈IM系统的架构设计
简述移动端IM开发的那些坑:架构设计、通信协议和客户端
一套原创分布式即时通讯(IM)系统理论架构方案
从零到卓越:京东客服即时通讯系统的技术架构演进历程
蘑菇街即时通讯/IM服务器开发之架构选择
腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT
微信技术总监谈架构:微信之道——大道至简(演讲全文)
如何解读《微信技术总监谈架构:微信之道——大道至简》
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
17年的实践:腾讯海量产品的技术方法论
>> 更多同类文章 ……

[6] 有关IM安全的文章:
即时通讯安全篇(一):正确地理解和使用Android端加密算法
即时通讯安全篇(二):探讨组合加密算法在IM中的应用
即时通讯安全篇(三):常用加解密算法与通讯安全讲解
即时通讯安全篇(四):实例分析Android中密钥硬编码的风险
传输层安全协议SSL/TLS的Java平台实现简介和Demo演示
理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)
微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享
>> 更多同类文章 ……

[7] 有关实时音视频开发:
即时通讯音视频开发(一):视频编解码之理论概述
即时通讯音视频开发(二):视频编解码之数字视频介绍
即时通讯音视频开发(三):视频编解码之编码基础
即时通讯音视频开发(四):视频编解码之预测技术介绍
即时通讯音视频开发(五):认识主流视频编码技术H.264
即时通讯音视频开发(六):如何开始音频编解码技术的学习
即时通讯音视频开发(七):音频基础及编码原理入门
即时通讯音视频开发(八):常见的实时语音通讯编码标准
即时通讯音视频开发(九):实时语音通讯的回音及回音消除概述
即时通讯音视频开发(十):实时语音通讯的回音消除技术详解
即时通讯音视频开发(十一):实时语音通讯丢包补偿技术详解
即时通讯音视频开发(十二):多人实时音视频聊天架构探讨
即时通讯音视频开发(十三):实时视频编码H.264的特点与优势
即时通讯音视频开发(十四):实时音视频数据传输协议介绍
即时通讯音视频开发(十五):聊聊P2P与实时音视频的应用情况
即时通讯音视频开发(十六):移动端实时音视频开发的几个建议
即时通讯音视频开发(十七):视频编码H.264、V8的前世今生
简述开源实时音视频技术WebRTC的优缺点
良心分享:WebRTC 零基础开发者教程(中文)
>> 更多同类文章 ……

[8] IM开发综合文章:
移动端IM开发需要面对的技术问题
开发IM是自己设计协议用字节流好还是字符流好?
请问有人知道语音留言聊天的主流实现方式吗?
IM系统中如何保证消息的可靠投递(即QoS机制)
谈谈移动端 IM 开发中登录请求的优化
完全自已开发的IM该如何设计“失败重试”机制?
微信对网络影响的技术试验及分析(论文全文)
即时通讯系统的原理、技术和应用(技术论文)
开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀
>> 更多同类文章 ……

[9] 开源移动端IM技术框架资料:
开源移动端IM技术框架MobileIMSDK:快速入门
开源移动端IM技术框架MobileIMSDK:常见问题解答
开源移动端IM技术框架MobileIMSDK:压力测试报告
开源移动端IM技术框架MobileIMSDK:Android版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:Java版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:iOS版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:Android客户端开发指南
开源移动端IM技术框架MobileIMSDK:Java客户端开发指南
开源移动端IM技术框架MobileIMSDK:iOS客户端开发指南
开源移动端IM技术框架MobileIMSDK:Server端开发指南
>> 更多同类文章 ……

[10] 有关推送技术的文章:
iOS的推送服务APNs详解:设计思路、技术原理及缺陷等
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
扫盲贴:认识MQTT通信协议
一个基于MQTT通信协议的完整Android推送Demo
求教android消息推送:GCM、XMPP、MQTT三种方案的优劣
移动端实时消息推送技术浅析
扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别
绝对干货:基于Netty实现海量接入的推送服务技术要点
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
为何微信、QQ这样的IM工具不使用GCM服务推送消息?
>> 更多同类文章 ……

[11] 更多即时通讯技术好文分类:
http://www.52im.net/forum.php?mod=collection&op=all

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:UDP中一个包的大小最大能多大下一篇:什么是MAC地址的老化时间

本帖已收录至以下技术专辑

推荐方案
评论 1
据说腾讯QQ这样的IM现在都改用PB了,不知是真是假
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部