当前位置: 首页 > 工具软件 > Yar > 使用案例 >

yar java_Yar 的传输协议学习以及 Java 版本的实现

汝臻
2023-12-01

在 yar 中规定的传输协议如下图所示,请求体为82个字节的yar_header_t和8字节的打包名称和请求实体yar_request_t,在yar_header_t里面用body_len记录8字节的打包名称+请求实体的长度;返回体类似,只是实体内容的结构体稍微不同,在reval里面才是实际最后客户端需要的结果。

整个传输以二进制流的形式传送。

在认识 Yar 协议之后,就是在 Java 中实现类似的数据结构和数据的二进制装包和解包,以及数据的传输了。为了记录自己一步步封装的过程,先使用比较过程的方式来实现这一个功能。

主要涉及到了三个类:YarClient类,传输和接受数据的实现;

YarProtocol类,按照上图的传输协议来把yar_header_t和packager_name还有yar_request_t(yar_response_t)写入二进制流,也就是拼装和解析传输数据;

JsonPackager类,实现对yar_request_t和yar_response_t的装包和拆包。

下面的代码只能提供整体的大概思路,如果要运行需要下载完整版的代码,在 Jdk 1.8 的环境下编译运行。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];

// 在这个8字节中,当是 php 或者是 json 的时候,后面的三个或者四个字节可能之前已经被占用,需要截取下

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;

}

}

 类似资料: