protobuf谷歌的开源序列化项目,类似的还有于json,xml等组织格式;据说protobuf的序列化占用的数据量最下,传输效率最高,并且作为服务器开发者,只需要掌握.proto文件的书写方式,就可以生成不同语言的序列化对象。这次讲解一下如何在服务器和安卓客户端之间利用protobuf传输数据。
测试的接口是登录功能:我写的proto文件如下:

syntax = "proto2";
message LoginUser{
  optional string name=1[default=""];
  optional string pass=2[default=""];
  optional int32 sex=3[default=0];
}

在ubuntu中,利用protoc 命令生成相关的java文件,然后复制到相应的目录中,这份java文件androud端和服务器端可以共用一份;
然后服务器端的测试接口如下:


public class LoginServer extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletHelp.set(req, resp);
        InputStream stream=req.getInputStream();
        LoginUser user=LoginUser.parseFrom(stream);
        if(user!=null){
            System.out.print(user.toString());
            LoginMsg msg=LoginMsg.newBuilder().setCode(200).setMsg("成功").build();
            resp.getOutputStream().write(msg.toByteArray());
        }
    }
}

然后启动服务等待链接,android端的代码如下:


                AsynTool.getInstance().submit(new Runnable() {
                    @Override
                    public void run() {
                        String loginname = name.getText().toString();
                        String loginpass = pass.getText().toString();
                        LoginUserOuterClass.LoginUser.Builder builder= LoginUserOuterClass.LoginUser.newBuilder();
                        builder.setName(loginname);
                        builder.setPass(loginpass);
                        LoginUserOuterClass.LoginUser user=builder.build();
                        try {
                            new HttpClient().post(SerAddUtils.getLogin(), user.toByteArray(), new HttpStreamCallback() {
                                @Override
                                public void getResult(InputStream stream) {
                                    try {
                                        final LoginMsgOuterClass.LoginMsg msg= LoginMsgOuterClass.LoginMsg.parseFrom(stream);
                                       runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                Toast.makeText(LoginActivity.this,msg.toString(),Toast.LENGTH_LONG).show();
                                            }
                                        });
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });

    public void post(String url,byte[] postdata,HttpStreamCallback callBack) throws  Exception{
        URL url1 = new URL(url);
        httpURLConnection = (HttpURLConnection) url1.openConnection();
        httpURLConnection.setRequestMethod("POST");
        if(HttpCookie.getInstance().get().getCookies()!=null&&HttpCookie.getInstance().get().getCookies().size()>0){
            httpURLConnection.setRequestProperty("Cookie","JSESSIONID="+HttpCookie.getInstance().get().getCookies().get(0).getValue());
        }
        httpURLConnection.setDoInput(true);
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setConnectTimeout(3000);
        BufferedOutputStream outputStream=new BufferedOutputStream(httpURLConnection.getOutputStream());
        outputStream.write(postdata);
        outputStream.flush();
        httpURLConnection.connect();
        if(httpURLConnection.getResponseCode()==200){
            Map<String, List<String>> head = httpURLConnection.getHeaderFields();
            InputStream stream = httpURLConnection.getInputStream();
            callBack.getResult(stream);
        }
    }

然后客户端进行测试:
测试结果如下:
如果客户端输入汉字,那么会会自动转换成utf-8编码,如果是英文或者数字,就不会;
如下客户端输入:
82727272 你好
服务端接收如下:
name: “82727272”
pass: “\344\275\240\345\245\275”
客户端输入:
82727272 abc
服务器接收:
name: “82727272”
pass: “abc”
感觉用这个很方便们可以省去对字段进行编码吗;并且protobuf可以判断字符是否是utf-8编码。因此在解码具体字段值的时候也很方便;不需要我们自己去定义数据结构;

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐