android与PC,C#与Java 利用protobuf 进行无障碍通讯【Socket】

来源:互联网 发布:淘宝t恤节 编辑:程序博客网 时间:2024/05/21 07:04

protobuf 是什么?

 Protocol buffers是一种编码方法构造的一种有效而可扩展的格式的数据。 谷歌使用其内部几乎RPC协议和文件格式的所有协议缓冲区。

 

参考文档

http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/overview.html 

  API的 参考文档 

 

protobuf 适用的语言

正宗(Google 自己内部用的)的protobuf支持三种语言:Java 、c++和Pyton,很遗憾的是并不支持.Net 或者 Lua 等语言,但社区的力量是不容忽视的,由于protobuf确实比Json、XML有速度上的优势和使用的方便,并且可以做到向前兼容、向后兼容等众多特点,所以protobuf社区又弄了个protobuf.net的组件并且还支持众多语言,详细可以看这个链接:http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns,具体某种语言的使用请各自对号入座,本篇只是讲使用android 与c++服务器通讯(测试过)或者与PC 通讯,使用java与C#之间互相通讯方面的DEMO,方面读者做参考。

 

使用protobuf协议

定义protobuf协议 

定义protobuf协议必须创建一个以.proto为后缀的文件,以本篇为例,本篇创建了一个叫msg.proto的消息文件,内容如下:

复制代码
package msginfo;

message CMsg
{
    required 
string msghead = 1;
    required 
string msgbody = 2;
}

message CMsgHead
{
    required int32 msglen 
= 1;
    required int32 msgtype 
= 2;
    required int32 msgseq 
= 3;
    required int32 termversion 
= 4;
    required int32 msgres 
= 5;
    required 
string termid = 6;
}

message CMsgReg
{
    optional int32 area 
= 1;
    optional int32 region 
= 2;
    optional int32 shop 
= 3;
    optional int32 ret 
= 4;
    optional 
string termid = 5[defalut="12345"];
}

message CMsgLogin
{
    optional int32 ret 
= 1;
}

message CMsgLogout
{
    optional int32 ret 
= 1;
复制代码

}

 

package在Java里面代表这个文件所在的包名,在c#里面代表该文件的命名空间,message代表一个类,

 required 代表该字段必填,optional 代表该字段可选,并可以为其设置默认值,默认值格式 :[defalut=字符串就是"123" ,整型就是 123]。

 

 

  如何编译该proto文件

java或android 使用的编译方法 

 正宗的proto可以在Linux下编译也有提供win版编译,由于Linux下编译要配置什么g++呀,之类的有点麻烦,之前做的步骤都忘得差不多,那还是回到win版编译吧,而net 版则是需要在win版下编译。

  正宗google 的protobuf 下载列表请参照:http://code.google.com/p/protobuf/downloads/list  ,选择其中的win版本下载。解压后会得到一个protoc.exe 文件,此时就可以开始编译了,先以java 为例,编译的步骤如下:

 

  • cmd 打开命令工具
  • 以我电脑为例,该exe 文件我放在F:\protoc 目录下,先cd 到该目录 cd F:\protoc
  •  
  • 再次进入目录后会发现该目录多了一个文件夹,即以该proto的package命名的的目录,会产生一个Msg.java的文件,这时这个文件就可以使用到我们的java或者 android 工程了。
  • 最后一步下载一个protobuf-java-2.3.0.jar的jar 包引用到你的java和android工程 里面,OK。可以使用你的protobuf了。如下图:
c#或者以后的Windows Phone 7 使用的编译方法:

.net 版的protobuf来源于proto社区,有两个版本。一个版本叫protobuf-net,官方站点:http://code.google.com/p/protobuf-net/  写法上比较符合c#一贯的写法。另一个版本叫protobuf-csharp-sport ,

 官方站点:http://code.google.com/p/protobuf-csharp-port/ 写法上跟java上的使用极其相似,比较遵循Google 的原生态写法,所以做跨平台还是选择第二版本吧。因为你会发现几乎和java的写法没啥两样,本篇也是使用这个版本。

 

进入该站点,下载你要的win版。 编译步骤如下:

  • 将刚才你的proto文件放在你解压出来的目录与protoc.exe 、ProtoGen.exe、ProtoGen.exe.config放于一起。其他文件可以删除或者 备份。
  • 还是打开命令行,定位于对应的目录里面,你放proto文件的目录里面。
  • 输入:protoc --descriptor_set_out=msg.protobin --include_imports msg.proto         
  • msg.protobin是要生成的prtobobin文件,可以使用这个bin文件生成cs文件
  • 再输入protogen msg.protobin  使用该bin文件生成cs文件,这样你就可以得到该 msg.cs 的CSharp版文件了,同时在VS里面使用要引入Google.ProtocolBuffers.dll。为了方便你可以将其做成一个批处理文件代码如下:
    echo on
    protoc 
    --descriptor_set_out=msg.protobin --include_imports msg.proto 
    protogen msg.protobin   

     将其另存为.bat文件即可

     

 

  使用protobuf编译后的文件来进行socket连接

android 与PC

android 做为客户端向PC的Java服务端发送数据,服务端得到数据进行解析,并打印出来 。

客户端代码:

复制代码
package net.testSocket;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import socket.exception.SmsClientException;
import socket.exception.SmsObjException;

import msginfo.Msg.CMsg;
import msginfo.Msg.CMsgHead;
import msginfo.Msg.CMsgReg;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.protobuf.InvalidProtocolBufferException;

//客户端的实现
public class TestSocket extends Activity {
    
private TextView text1;
    
private Button but1; 
    Socket socket 
= null;

    
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        
// Thread desktopServerThread=new Thread(new AndroidServer());
        
// desktopServerThread.start();

        setContentView(R.layout.main);

        text1 
= (TextView) findViewById(R.id.text1);
        but1 
= (Button) findViewById(R.id.but1); 

        but1.setOnClickListener(
new Button.OnClickListener() {
            @Override
            
public void onClick(View v) {

                
// edit1.setText("");
                
// Log.e("dddd", "sent id");
                
// new Thread() {
                
// public void run() {
                try {
                    
// socket=new Socket("192.168.1.102",54321);
                    
//socket = new Socket("192.168.1.110", 10527);
                     socket = new Socket("192.168.1.116"12345);
                    
//得到发送消息的对象 
                    
//SmsObj smsobj = new SmsObj(socket);
                    
                    
//设置消息头和消息体并存入消息里面
                    
// head
                    CMsgHead head = CMsgHead.newBuilder().setMsglen(5)
                            .setMsgtype(
1).setMsgseq(3).setTermversion(41)
                            .setMsgres(
5).setTermid("11111111").build();

                    
// body
                    CMsgReg body = CMsgReg.newBuilder().setArea(22)
                            .setRegion(
33).setShop(44).build();

                    
// Msg
                    CMsg msg = CMsg.newBuilder()
                            .setMsghead(head.toByteString().toStringUtf8())
                            .setMsgbody(body.toByteString().toStringUtf8())
                            .build();

                    
// PrintWriter out = new PrintWriter(new BufferedWriter(
                    
// new OutputStreamWriter(socket.getOutputStream())),
                    
// true);
                    
// out.println(m.toString());
                    
// out.println(m.toByteString().toStringUtf8());

                    
// 向服务器发送信息
                    msg.writeTo(socket.getOutputStream());
                    
//byte[] b = msg.toByteArray();
                    
//smsobj.sendMsg(b);

                    
// System.out.println("====msg==="
                    
// + m.toByteString().toStringUtf8());
                    
                    
// byte[] backBytes = smsobj.recvMsg();
                    
//
                    
// 接受服务器的信息
                    InputStream input = socket.getInputStream();

                    
// DataInputStream dataInput=new DataInputStream();
                    
//byte[] by = smsobj.recvMsg(input);
                    byte[] by=recvMsg(input);
                    setText(CMsg.parseFrom(by));

                    
// BufferedReader br = new BufferedReader(
                    
// new InputStreamReader(socket.getInputStream()));
                    
// String mstr = br.readLine();
                    
// if (!str .equals("")) {
                    
// text1.setText(str);
                    
// } else {
                    
// text1.setText("数据错误");
                    
// }
                    
// out.close();
                    
// br.close();

                    input.close();
                    
//smsobj.close();
                    socket.close();
                } 
catch (UnknownHostException e) {
                    e.printStackTrace();
                } 
catch (IOException e) {
                    e.printStackTrace();
                } 
catch (Exception e) {
                    System.
out.println(e.toString());
                }
                
// };
                
// }.start();

            }
        });

    }
    
    
/**
     * 接收server的信息
     * 
     * @return
     * @throws SmsClientException
     * @author fisher
     
*/
    
public byte[] recvMsg(InputStream inpustream) throws SmsObjException {
        
try {
 
            
byte len[] = new byte[1024];
            
int count = inpustream.read(len);  
        
            
byte[] temp = new byte[count];
            
for (int i = 0; i < count; i++) {   
                    temp[i] 
= len[i];                              
            } 
            
return temp;
        } 
catch (Exception localException) {
            
throw new SmsObjException("SmapObj.recvMsg() occur exception!"
                    
+ localException.toString());
        }
    }

    
/**
     * 得到返回值添加到文本里面
     * 
     * @param g
     * @throws InvalidProtocolBufferException
     
*/
    
public void setText(CMsg g) throws InvalidProtocolBufferException {
        CMsgHead h 
= CMsgHead.parseFrom(g.getMsghead().getBytes());
        StringBuffer sb 
= new StringBuffer();
        
if (h.hasMsglen())
            sb.append(
"==len===" + h.getMsglen() + "\n");
        
if (h.hasMsgres())
            sb.append(
"==res===" + h.getMsgres() + "\n");
        
if (h.hasMsgseq())
            sb.append(
"==seq===" + h.getMsgseq() + "\n");
        
if (h.hasMsgtype())
            sb.append(
"==type===" + h.getMsgtype() + "\n");
        
if (h.hasTermid())
            sb.append(
"==Termid===" + h.getTermid() + "\n");
        
if (h.hasTermversion())
            sb.append(
"==Termversion===" + h.getTermversion() + "\n");

        CMsgReg bo 
= CMsgReg.parseFrom(g.getMsgbody().getBytes());
        
if (bo.hasArea())
            sb.append(
"==area==" + bo.getArea() + "\n");
        
if (bo.hasRegion())
            sb.append(
"==Region==" + bo.getRegion() + "\n");
        
if (bo.hasShop())
            sb.append(
"==shop==" + bo.getShop() + "\n");
        
if (bo.hasRet())
            sb.append(
"==Ret==" + bo.getRet() + "\n");
        
if (bo.hasTermid())
            sb.append(
"==Termid==" + bo.getTermid() + "\n");

        text1.setText(sb.toString());
    }
复制代码

}

 

服务端代码:

 package server;

复制代码

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

import msginfo.Msg.CMsg;
import msginfo.Msg.CMsgHead;
import msginfo.Msg.CMsgReg;

public class AndroidServer implements Runnable {

    
public void run() {
        
try {
            System.
out.println("beign:");
            ServerSocket serverSocket 
= new ServerSocket(12345);
            
while (true) {
                System.
out.println("等待接收用户连接:");
                
// 接受客户端请求
                Socket client = serverSocket.accept();

                DataOutputStream dataOutputStream;
                DataInputStream dataInputStream;

                
try {
                    
// 接受客户端信息
                    
// BufferedReader in = new BufferedReader(
                    
// new InputStreamReader(client.getInputStream()));
                    
// String str = in.readLine();
                    
// System.out.println("read length:  " + str.length());
                    
// System.out.println("read:  " + str);

                    
// InputStream inputstream = client.getInputStream();
                    
// byte[] buffer = new byte[1024 * 4];
                    
// int temp = 0;
                    
// while ((temp = inputstream.read(buffer)) != -1) {
                    
// str = new String(buffer, 0, temp);
                    
// System.out.println("===str===" + str);

                    
// File file = new File("user\\log\\login.log");
                    
// appendLog(file, str);

                    InputStream inputstream 
= client.getInputStream();

                    dataOutputStream 
= new DataOutputStream(
                            client.getOutputStream());
                    
//dataInputStream = new DataInputStream(inputstream);

                    
// byte[] d = new BufferedReader(new InputStreamReader(
                    
// dataInputStream)).readLine().getBytes();
                    
// byte[] bufHeader = new byte[4];
                    
// dataInputStream.readFully(bufHeader);
                    
// int len = BytesUtil.Bytes4ToInt(bufHeader);
                    
// System.out.println(d.length);
                    
// System.out.println(dataInputStream.readLine().toString());
                    byte len[] = new byte[1024];
                    
int count = inputstream.read(len);  
                
                    
byte[] temp = new byte[count];
                    
                    
for (int i = 0; i < count; i++) {   
                        
                            temp[i] 
= len[i];                              
                    } 

                    
// 协议正文
//                     byte[] sendByte = new byte[30];
//                    
//                     dataInputStream.readFully(sendByte);
//                     for (byte b : sendByte) {
//                     System.out.println(""+b);
//                     }
                    CMsg msg = CMsg.parseFrom(temp);
                    
//
                    
//
                    CMsgHead head = CMsgHead.parseFrom(msg.getMsghead()
                            .getBytes());
                    System.
out.println("==len===" + head.getMsglen());
                    System.
out.println("==res===" + head.getMsgres());
                    System.
out.println("==seq===" + head.getMsgseq());
                    System.
out.println("==type===" + head.getMsgtype());
                    System.
out.println("==Termid===" + head.getTermid());
                    System.
out.println("==Termversion==="
                            
+ head.getTermversion());

                    CMsgReg body 
= CMsgReg.parseFrom(msg.getMsgbody()
                            .getBytes());
                    System.
out.println("==area==" + body.getArea());
                    System.
out.println("==Region==" + body.getRegion());
                    System.
out.println("==shop==" + body.getShop());

                    
// PrintWriter out = new PrintWriter(new BufferedWriter(
                    
// new OutputStreamWriter(client.getOutputStream())),
                    
// true);
                    
// out.println("return    " +msg.toString());

                    
// in.close();
                    
// out.close();

                    sendProtoBufBack(dataOutputStream);

                    inputstream.close();
                    
//dataInputStream.close();
                } catch (Exception ex) {
                    System.
out.println(ex.getMessage());
                    ex.printStackTrace();
                } 
finally {
                    client.close();
                    System.
out.println("close");
                }
            }
        } 
catch (IOException e) {
            System.
out.println(e.getMessage());
        }
    }

    
public static void main(String[] args) {
        Thread desktopServerThread 
= new Thread(new AndroidServer());
        desktopServerThread.start();
    }

    
private byte[] getProtoBufBack() {

        
// head
        CMsgHead head = CMsgHead.newBuilder().setMsglen(5)
                .setMsgtype(
1).setMsgseq(3).setTermversion(41)
                .setMsgres(
5).setTermid("11111111").build();

        
// body
        CMsgReg body = CMsgReg.newBuilder().setArea(22)
                .setRegion(
33).setShop(44).build();

        
// Msg
        CMsg msg = CMsg.newBuilder()
                .setMsghead(head.toByteString().toStringUtf8())
                .setMsgbody(body.toByteString().toStringUtf8())
                .build();

        
return msg.toByteArray();
    }

    
private void sendProtoBufBack(DataOutputStream dataOutputStream) {

        
byte[] backBytes = getProtoBufBack();
        
// 协议头部
    
//    Integer len2 = backBytes.length;
        
// 前四个字节,标示协议正文长度
    
//    byte[] cmdHead2 = BytesUtil.IntToBytes4(len2);

        
try {
            
//dataOutputStream.write(cmdHead2, 0, cmdHead2.length);
            dataOutputStream.write(backBytes, 0, backBytes.length);
            dataOutputStream.flush();
        } 
catch (IOException e) {
            e.printStackTrace();
        }
    }

}
复制代码

 最后得到的效果:

客户端:

 

 服务端:

 

 

protobuf .net版的实现代码如下:

复制代码
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Google.ProtocolBuffers;
using msginfo;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace protobuf_csharp_sport
{
    
class Program
    {
        
private static ManualResetEvent allDone = new ManualResetEvent(false);

        
static void Main(string[] args)
        {
            beginProtocbuf();
        }

        
private static void beginProtocbuf()
        {
            
//启动服务端
            TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 12345);
            server.Start();
            server.BeginAcceptTcpClient(clientConnected, server); 
            Console.WriteLine(
"SERVER : 等待数据 ---");

            
//启动客户端
            ThreadPool.QueueUserWorkItem(runClient);
            allDone.WaitOne();

            Console.WriteLine(
"SERVER : 退出 ---");
            
// server.Stop();
        }

        
//服务端处理
        private static void clientConnected(IAsyncResult result)
        {
            
try
            {
                TcpListener server 
= (TcpListener)result.AsyncState;
                
using (TcpClient client = server.EndAcceptTcpClient(result))
                {
                    
using (NetworkStream stream = client.GetStream())
                    {
                        
//获取
                        Console.WriteLine("SERVER : 客户端已连接,数据读取中 --- ");
                        
byte[] myRequestBuffer = new byte[1024];

                        
int myRequestLength = 0;
                        
do
                        {
                            myRequestLength 
= stream.Read(myRequestBuffer, 0, myRequestBuffer.Length);
                        }
                        
while (stream.DataAvailable);
                         
                        CMsg msg 
= CMsg.ParseFrom(myRequestBuffer.RemoveEmptyByte(myRequestLength));

                        CMsgHead head 
= CMsgHead.ParseFrom(Encoding.ASCII.GetBytes(msg.Msghead));
                        CMsgReg body 
= CMsgReg.ParseFrom(Encoding.ASCII.GetBytes(msg.Msgbody));

                        IDictionary
<Google.ProtocolBuffers.Descriptors.FieldDescriptor, object> d = head.AllFields;
                        
foreach (var item in d)
                        {
                            Console.WriteLine(item.Value.ToString());
                        }

                        d 
= body.AllFields;
                        Console.WriteLine(
"===========================================");
                        
foreach (var item in d)
                        {
                            Console.WriteLine(item.Value.ToString());
                        }
                      
                        Console.WriteLine(
"SERVER : 响应成功 ---");

                        Console.WriteLine(
"SERVER: 关闭连接 ---");
                        stream.Close();
                    }
                    client.Close();
                }
            }
            
finally
            {
                allDone.Set();
            }
        }

        
//客户端请求
        private static void runClient(object state)
        {
            
try
            {
                CMsgHead head 
= CMsgHead.CreateBuilder()
                    .SetMsglen(
5)
                    .SetMsgtype(
1)
                    .SetMsgseq(
3)
                    .SetTermversion(
4)
                    .SetMsgres(
5)
                    .SetTermid(
"11111111")
                    .Build();

                CMsgReg body 
= CMsgReg.CreateBuilder().
                    SetArea(
22)
                   .SetRegion(
33)
                   .SetShop(
44)
                   .Build();

                CMsg msg 
= CMsg.CreateBuilder()
                    .SetMsghead(head.ToByteString().ToStringUtf8())
                    .SetMsgbody(body.ToByteString().ToStringUtf8())
                    .Build();


                Console.WriteLine(
"CLIENT : 对象构造完毕 ...");

                
using (TcpClient client = new TcpClient())
                {
                    
// client.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.116"), 12345));
                    client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345));
                    Console.WriteLine(
"CLIENT : socket 连接成功 ...");

                    
using (NetworkStream stream = client.GetStream())
                    {
                        
//发送
                        Console.WriteLine("CLIENT : 发送数据 ...");
                      
                        msg.WriteTo(stream);

                        
//关闭
                        stream.Close();
                    }
                    client.Close();
                    Console.WriteLine(
"CLIENT : 关闭 ...");
                }
            }
            
catch (Exception error)
            {
                Console.WriteLine(
"CLIENT ERROR : {0}", error.ToString());
            }
        }

    }
//end class



    
public static class ExtensionClass {
        
public static byte[] RemoveEmptyByte(this byte[] by,int length) 
        {
            
byte[] returnByte = new byte[length];

            
for (int i = 0; i < length; i++)
            {
                returnByte[i] 
= by[i];
            }
            
return returnByte;

        }
    }
复制代码

} 

 

 运行的效果:

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 拍拍贷律师函寄到家里了怎么办 欠了拍拍贷本息一万多了怎么办 把人偷小孩的人贩子打死了怎么办 怀孕3个月没有胎心怎么办 社保局打印关系转移信封之后怎么办 长裙变装外出被发现了怎么办 超变陀螺怎么绳子拉不出来怎么办 梦幻诛仙传说时间得不到东西怎么办 夹在强势母亲和强势老公中间怎么办 工作调动校长总拖着不盖章怎么办 宝贝在妈妈肚子里发育慢怎么办 领导安排你负责一次讲座你怎么办 雷蛇北海巨妖耳机有回音怎么办 手机直播声卡有杂音有回音怎么办 大班见到陌生人入园怎么办安全教案 两首歌合并到一起中间有停顿怎么办 想做主持人但不是播音专业怎么办 动脉造影术2天后穿刺点出血怎么办 战舰世界买了重复金币船怎么办 戒指戴在手上取不下来怎么办 工作中难以和同事上司相处怎么办 老是被上司和同事欺负我该怎么办 桌面太低座位太高写字不舒服怎么办 一个人如果欠下网贷无法偿还怎么办 c语言的编译和运行不见了怎么办 8k纸的国庆节手抄报怎么办 合同员工签字了老板一直未签怎么办 下体长毛了很多肉芽很痒怎么办 对方拟把假离婚协议弄假成真怎么办 领主之塔改版后旧材料怎么办 汽车遥控钥匙打不开车门怎么办 苹果手机访问限制密码忘了怎么办 苹果的访问限制密码忘了怎么办 手机下雨天进水声音出了问题怎么办 胸太小了该怎么办经常揉胸会变大吗 鼻冲洗器冲鼻子耳朵进水怎么办 手表进水了然后里面有水珠怎么办 玩游戏后头晕恶心想吐怎么办 吃完美林3小时后又发烧怎么办 颜值和身材都是负分怎么办 妈妈离婚又有一个孩子我该怎么办