yar java_Yar 的传输协议学习以及 Java 版本的实现
在 yar 中規(guī)定的傳輸協(xié)議如下圖所示,請求體為82個(gè)字節(jié)的yar_header_t和8字節(jié)的打包名稱和請求實(shí)體yar_request_t,在yar_header_t里面用body_len記錄8字節(jié)的打包名稱+請求實(shí)體的長度;返回體類似,只是實(shí)體內(nèi)容的結(jié)構(gòu)體稍微不同,在reval里面才是實(shí)際最后客戶端需要的結(jié)果。
整個(gè)傳輸以二進(jìn)制流的形式傳送。
在認(rèn)識 Yar 協(xié)議之后,就是在 Java 中實(shí)現(xiàn)類似的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)的二進(jìn)制裝包和解包,以及數(shù)據(jù)的傳輸了。為了記錄自己一步步封裝的過程,先使用比較過程的方式來實(shí)現(xiàn)這一個(gè)功能。
主要涉及到了三個(gè)類:YarClient類,傳輸和接受數(shù)據(jù)的實(shí)現(xiàn);
YarProtocol類,按照上圖的傳輸協(xié)議來把yar_header_t和packager_name還有yar_request_t(yar_response_t)寫入二進(jìn)制流,也就是拼裝和解析傳輸數(shù)據(jù);
JsonPackager類,實(shí)現(xiàn)對yar_request_t和yar_response_t的裝包和拆包。
下面的代碼只能提供整體的大概思路,如果要運(yùn)行需要下載完整版的代碼,在 Jdk 1.8 的環(huán)境下編譯運(yùn)行。package?yar;
import?yar.packager.YarPackager;
import?yar.protocol.YarRequest;
import?yar.protocol.YarResponse;
import?java.io.*;
import?java.lang.reflect.Proxy;
import?java.net.URL;
import?java.net.URLConnection;
import?java.util.HashMap;
/**
*?Created?by?zhoumengkang?on?2/12/15.
*/
public?class?YarClient?{
private?String?uri;
private?String?packager;
public?YarClient(String?uri){
this.uri?=?uri;
this.packager?=?YarConfig.getString("yar.packager");
}
public?final?Object?useService(Class?type)?{
YarClientInvocationHandler?handler?=?new?YarClientInvocationHandler(this);
if?(type.isInterface())?{
return?Proxy.newProxyInstance(type.getClassLoader(),?new?Class[]{type},?handler);
}?else?{
return?Proxy.newProxyInstance(type.getClassLoader(),?type.getInterfaces(),?handler);
}
}
public?Object?invoke(String?method,Object[]?args){
YarRequest?yarRequest?=?new?YarRequest();
yarRequest.setId(123456789);
yarRequest.setMethod(method);
yarRequest.setParameters(args);
yarRequest.setPackagerName(this.packager);
byte[]?res?=?null;
try?{
res?=?sendPost(this.uri,?YarProtocol.requestCreate(yarRequest));
}?catch?(IOException?e)?{
e.printStackTrace();
}
YarResponse?yarResponse?=?YarProtocol.responseFetch(res);
assert?yarResponse?!=?null;
return?yarResponse.getRetVal();
}
public?static?byte[]?sendPost(String?url,?byte[]?content)?{
OutputStream?out?=?null;
InputStream?in?=?null;
byte[]?b?=?null;
try?{
URL?realUrl?=?new?URL(url);
URLConnection?conn?=?realUrl.openConnection();
conn.setRequestProperty("accept",?"*/*");
conn.setRequestProperty("connection",?"Keep-Alive");
conn.setDoOutput(true);
conn.setDoInput(true);
out?=?conn.getOutputStream();
out.write(content);
out.flush();
out.close();
in?=?conn.getInputStream();
b?=?new?byte[in.available()];
in.read(b);
in.close();
}?catch?(Exception?e)?{
e.printStackTrace();
}?finally?{
try?{
if?(out?!=?null)?{
out.close();
}
if?(in?!=?null)?{
in.close();
}
}?catch?(IOException?ex)?{
ex.printStackTrace();
}
}
return?b;
}
}package?yar;
import?yar.packager.YarPackager;
import?yar.protocol.*;
import?java.io.*;
import?java.util.Arrays;
/**
*?Created?by?zhoumengkang?on?5/12/15.
*/
public?class?YarProtocol?{
public?static?final?int?YAR_PROTOCOL_MAGIC_NUM?=?0x80DFEC60;
public?static?final?int?YAR_HEADER_LENGTH?=?82;
public?static?final?int?YAR_PACKAGER_NAME_LENGTH?=?8;
public?static?YarHeader?render(YarRequest?yarRequest,int?length){
YarHeader?yarHeader?=?new?YarHeader();
yarHeader.setId((int)?yarRequest.getId());
yarHeader.setMagicNum(YAR_PROTOCOL_MAGIC_NUM);
yarHeader.setBodyLen(length);
yarHeader.setProvider(YarConfig.getString("yar.provider"));
yarHeader.setToken(YarConfig.getString("yar.token"));
return?yarHeader;
}
public?static?YarHeader?parse(byte[]?content){
YarHeader?yarHeader?=?new?YarHeader();
DataInputStream?in?=?new?DataInputStream(new?ByteArrayInputStream(content));
try?{
yarHeader.setId(in.readInt());
yarHeader.setVersion(in.readShort());
if?(in.readInt()?!=?YAR_PROTOCOL_MAGIC_NUM)?{
return?null;
}
yarHeader.setReserved(in.readInt());
byte[]?provider?=?new?byte[32];
in.read(provider,0,32);
yarHeader.setProvider(new?String(provider));
byte[]?token?=?new?byte[32];
in.read(token,0,32);
yarHeader.setToken(new?String(token));
yarHeader.setBodyLen(in.readInt());
}?catch?(IOException?e)?{
e.printStackTrace();
}?finally?{
try?{
in.close();
}?catch?(IOException?e)?{
e.printStackTrace();
}
}
return?yarHeader;
}
public?static?YarResponse?responseFetch(byte[]?responseByte){
YarResponse?yarResponse?=?new?YarResponse();
byte[]?header?=?new?byte[YAR_HEADER_LENGTH];
for?(int?i?=?0;?i?
header[i]?=?responseByte[i];
}
YarHeader?yarHeader?=?YarProtocol.parse(header);
byte[]?packager?=?new?byte[YAR_PACKAGER_NAME_LENGTH];
int?packagerLength?=?0;
for?(int?i?=?0;?i?
packager[i]?=?responseByte[YAR_HEADER_LENGTH?+?i];
//?在這個(gè)8字節(jié)中,當(dāng)是?php?或者是?json?的時(shí)候,后面的三個(gè)或者四個(gè)字節(jié)可能之前已經(jīng)被占用,需要截取下
if?(packager[i]?==?0){
packagerLength?=?i;
break;
}
}
String?packagerName?=?new?String(packager);
YarClient.debug(packagerName);
yarResponse.setPackagerName(packagerName.substring(0,?packagerLength));
int?off?=?YAR_HEADER_LENGTH?+?YAR_PACKAGER_NAME_LENGTH;
int?len?=?responseByte.length;
byte[]?yarResponseBody?=?new?byte[len];
for?(int?i?=?off;?i?
yarResponseBody[i?-?off]?=?responseByte[i];
}
try?{
return?YarPackager.get(yarResponse.getPackagerName()).unpack(yarResponseBody);
}?catch?(Exception?e)?{
e.printStackTrace();
}
return?null;
}
public?static?byte[]?requestCreate(YarRequest?yarRequest)?throws?IOException?{
byte[]?body;
ByteArrayOutputStream?bodyOut?=?new?ByteArrayOutputStream();
try?{
bodyOut.write(Arrays.copyOf(yarRequest.getPackagerName().toUpperCase().getBytes(),?8));
bodyOut.write(YarPackager.get(yarRequest.getPackagerName()).pack(yarRequest));
body?=?bodyOut.toByteArray();
}?catch?(Exception?e)?{
e.printStackTrace();
return?null;
}?finally?{
bodyOut.close();
}
YarHeader?yarHeader?=?render(yarRequest,body.length);
ByteArrayOutputStream?byteArrayOutputStream?=?new?ByteArrayOutputStream();
DataOutputStream?out?=?new?DataOutputStream(byteArrayOutputStream);
try?{
out.writeInt(yarHeader.getId());
out.writeShort(yarHeader.getVersion());
out.writeInt(yarHeader.getMagicNum());
out.writeInt(yarHeader.getReserved());
out.write(Arrays.copyOf(yarHeader.getProvider().getBytes(),32));
out.write(Arrays.copyOf(yarHeader.getToken().getBytes(),32));
out.writeInt(yarHeader.getBodyLen());
out.write(body);
return?byteArrayOutputStream.toByteArray();
}?finally?{
byteArrayOutputStream.close();
out.close();
}
}
}package?yar.packager;
import?org.json.JSONObject;
import?yar.YarClient;
import?yar.protocol.YarRequest;
import?yar.protocol.YarResponse;
import?java.util.Map;
/**
*?Created?by?zhoumengkang?on?4/12/15.
*/
public?class?JsonPackager?extends?YarPackager?{
@Override
public?byte[]?pack(YarRequest?yarRequest)?{
Map?request?=?requestFormat(yarRequest);
JSONObject?jsonObject?=?new?JSONObject(request);
String?string?=?jsonObject.toString();
return?string.getBytes();
}
@Override
public?YarResponse?unpack(byte[]?content)?{
JSONObject?jsonObject?=?new?JSONObject(new?String(content));
YarClient.debug(jsonObject);
YarResponse?yarResponse?=?new?YarResponse();
yarResponse.setId(jsonObject.getLong("i"));
yarResponse.setStatus(jsonObject.getInt("s"));
yarResponse.setOut(jsonObject.getString("o"));
yarResponse.setRetVal(jsonObject.get("r"));
return?yarResponse;
}
}
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的yar java_Yar 的传输协议学习以及 Java 版本的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 栈内存结构_JVM内存结构概念
- 下一篇: java 迪杰斯特拉_Java 实现Di