一 今天测试了下json和protobuf的大小
过程如下:
1.将protobuf的编译器protoc.exe放到测试项目testprotobuf根目录下
2.在testprotobuf下新建一个文件夹prof,并建立文件proto文件 test.proto
package tutorial;
option java_package = "com.example.testbean";
option java_outer_classname = "TestBean";
message Person {
optional string str = 1;
optional int32 int = 2;
optional double dbl = 3;
optional bool b=4;
optional sint32 sint=5;
}
3.cmd进入testprotobuf里 输入命令protoc --java_out=./src prof/test.proto自动生成TestBean文件
4.将编译好的protobuf-java-2.5.0.jar放到classpath里
5.新建AddPerson.java
package com.example.testbean;
import org.vertx.java.core.json.JsonObject;
import com.example.testbean.TestBean.Person;
public class AddPerson {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Person.Builder person=Person.newBuilder();
boolean b=true;
person.setB(b);
byte[] bArray=person.build().toByteArray();
System.out.println("boolean|"+b+":"+bArray.length);
double dbl=2.11457;
person.clear();
person.setDbl(dbl);
bArray=person.build().toByteArray();
System.out.println("double|"+dbl+":"+bArray.length);
int intp=3000;
person.clear();
person.setInt(intp);
bArray=person.build().toByteArray();
System.out.println("int|"+intp+":"+bArray.length);
int intn=-3000;
person.clear();
person.setInt(intn);
bArray=person.build().toByteArray();
System.out.println("int|"+intn+":"+bArray.length);
person.clear();
person.setSint(intn);
bArray=person.build().toByteArray();
System.out.println("ints|"+intn+":"+bArray.length);
person.clear();
String s="test";
person.setStr(s);
bArray=person.build().toByteArray();
System.out.println("string|"+s+":"+bArray.length);
System.out.println("--------");
JsonObject js=new JsonObject();
js.putBoolean("b",b );
bArray=js.encode().getBytes();
System.out.println("boolean|"+b+":"+bArray.length);
js=new JsonObject();
js.putNumber("d",dbl );
bArray=js.encode().getBytes();
System.out.println("double|"+dbl+":"+bArray.length);
js=new JsonObject();
js.putNumber("i",intp );
bArray=js.encode().getBytes();
System.out.println("int|"+intp+":"+bArray.length);
js=new JsonObject();
js.putNumber("n",intn );
bArray=js.encode().getBytes();
System.out.println("int|"+intn+":"+bArray.length);
js=new JsonObject();
js.putString("s",s );
bArray=js.encode().getBytes();
System.out.println("String|"+s+":"+bArray.length);
}
}
测试结果如下:
boolean|true:2
double|2.11457:9
int|3000:3
int|-3000:11
ints|-3000:3
string|test:6
--------
boolean|true:10
double|2.11457:13
int|3000:10
int|-3000:11
String|test:12
根据上面可以看出
1.json基本上把所有数据当做字符串进行传输。所以类似于double数据,位数越多,越占空间,而protobuf则不然,不管多长的double类型,protobuf都是9位byte(改变double位数可以看出来这点)。
2.protobuf sint对于负数的优化能力是很强的。
3.protobuf是根据数据类型进行优化的。根据文档protobuf对于数组进行了encode操作,具体文档https://developers.google.com/protocol-buffers/docs/encoding,个人表示没看懂。
4.对于json来说 key和“{”,“[”也是需要占用空间,但是对于protobuf来说 key 用1,2,3来代替。只占用1个btye 但是16以后就是2个btye。
结论:
是否使用还是得根据数据类型来决定。
二 Vertx的服务器和客户端
之前写的vertx例子 都无法在Eclipse直接启动。根据这篇文章进行设置才能能启动http://my.oschina.net/wstone/blog/151881。
1. 首先下载vert.x-2.0.2-final.zip,然后解压到一个目录里.
2. 在Eclipse里创建一个空的Java项目.
3. 在Eclipse里创建一个User Lib: "Vert.x",把Vert.x的Lib目录下的jar文件全部加入.
4. 创建一个新的的Debug配置,打开配置窗口,把新建的项目从Classpath页的User Entries里删除掉,然后添加UserLib库"Vert.x",再添加Vert.X安装目录下的conf目录
5. 把Main页里的Main class:改成: org.vertx.java.platform.impl.cli.Starter
6. 把Arguments页里的Program arguments改成:"run 需要测试的vertile类名 -cp ${project_loc:项目名}/编译类的输出目录";
把Working directory设置成Vert.x的安装目录.
7. 在Source页里把新建的项目添加进Source Lookup Path里
8. 保存调试配置,至此完成!
三 服务端和客户端整合protobuf服务端代码
package com.test;
import org.vertx.java.core.Handler;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.net.NetSocket;
import org.vertx.java.platform.Verticle;
import com.test.TestBean.Person;
public class TestServer extends Verticle {
public Person buildPerson(){
Person.Builder person=Person.newBuilder();
boolean b=true;
person.setB(true);
person.setDbl(2.141);
person.setStr("abc");
return person.build();
}
@Override
public void start() {
vertx.createNetServer().connectHandler(new Handler<NetSocket>() {
@Override
public void handle(final NetSocket socket) {
socket.dataHandler(new Handler<Buffer>(){
@Override
public void handle(Buffer buffer){
System.out.println(buffer.length());
Buffer buf=new Buffer();
Person person=buildPerson();
buf.appendBytes(person.toByteArray());
socket.write(buf);
}
});
}
}).listen(1234);
}
}
客户端代码
package com.test;
import org.vertx.java.core.AsyncResult;
import org.vertx.java.core.AsyncResultHandler;
import org.vertx.java.core.Handler;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.net.NetSocket;
import org.vertx.java.platform.Verticle;
import com.test.TestBean.Person;
public class TestClient extends Verticle {
public void start(){
vertx.createNetClient().connect(1234, "localhost", new AsyncResultHandler<NetSocket>() {
public void handle(AsyncResult<NetSocket> asyncResult){
if(asyncResult.succeeded()){
NetSocket socket = asyncResult.result();
socket.dataHandler(new Handler<Buffer>() {
public void handle(Buffer buffer) {
System.out.println("Net client receiving: " + buffer);
try{
Person p=Person.parseFrom(buffer.getBytes());
System.out.println(p.getDbl());
System.out.println(p.getStr());
}catch(Exception e){
e.printStackTrace();
}
}
});
//Now send some data
for (int i = 0; i < 10; i++) {
String str = "hello" + i + "\n";
System.out.print("Net client sending: " + str);
socket.write(new Buffer(str));
}
}else{
asyncResult.cause().printStackTrace();
}
}
});
}
}
整合遇到的问题,将protobuf-java-2.5.0.jar放到classpath里,启动服务器始终报错,找不到person类。尝试clean project失败,怀疑是vertx没找准路径。
解决:将protobuf-java-2.5.0.jar 放到vert.x 个user lib里就可以了。