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编码。因此在解码具体字段值的时候也很方便;不需要我们自己去定义数据结构;
