在网络通信时通常我们有传输字符串或二进制两种方式
这里以websocket为例,
传输字符串在frame->ws中能够看到每次通信传输的内容
传输二进制只能看到 Binary Frame
字符串
一般传输字符串可以直接传输json,协议头可以采用
{"login":{"username":"' + username + '","password":"' + password + '"}}'
这种方式表明 协议头为login
数据为{"username":"' + username + '","password":"' + password + '"}
,到了后端,直接转化成JSONArray,然后遍历既可以取出头部和数据内容。
二进制
传输二进制一般使用protobuf就可以
byte.writeInt(123);
byte.writeBytes("数据");
协议头为123
数据为 数据
,然后后端就可以根据协议头判断是什么请求了,byte可以写类型还有 writeShort
等,区别在于字节长度不同,用什么长度写,后台 就要用什么长度读。
比如 java ByteBuffer
int header = byteBuffer.getInt();
这样就可以把协议头读取出来了,然后再接着读取byteBuffer,比如转化protobuf格式。
protobuf
这是谷歌推出的二进制通信工具
- java
pom
<!-- protobuf依赖-->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.protobuf-java-format</groupId>
<artifactId>protobuf-java-format</artifactId>
<version>1.4</version>
</dependency>
配置文件
@Configuration
public class ProtobufConfig {
/**
* protobuf 序列化
*/
@Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
/**
* protobuf 反序列化
*/
@Bean
RestTemplate restTemplate(ProtobufHttpMessageConverter protobufHttpMessageConverter) {
return new RestTemplate(Collections.singletonList(protobufHttpMessageConverter));
}
}
使用
先新建一个game_msg.proto文件
syntax = "proto3";
package com.xxx.xxx.xxx;
message Msg {
string type = 1;
string json = 2;
}
然后下载protoc.exe把文件转化为class,在github上下载,不要选带语言的,那是源码,选择windows x64。
添加环境变量,然后运行如下指令
protoc --java_out=./admin/src/main/java ./admin/src/main/java/game_msg.proto
//protoc --java_out=输出路径 .proto文件路径
下面是操作protobuf
GameMsg.Msg.Builder builder = GameMsg.Msg.newBuilder();
builder = builder.mergeFrom(conver(byteBuffer));//byte[]转protobuf
builder.build().toByteArray();//protobuf转byte[]
System.out.println("来自客户端的消息:" + builder.getType()+";"+builder.getJson());
//ByteBuffer 转化 byte[]必须调用完后flip()才可以调用此方法
public static byte[] conver(ByteBuffer byteBuffer){
int len = byteBuffer.limit() - byteBuffer.position();
byte[] bytes = new byte[len];
if(byteBuffer.isReadOnly()){
return null;
}else {
byteBuffer.get(bytes);
}
return bytes;
}