網絡通信時通常我們傳輸字符串或二進制
這裏以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;
}