移动开发中的通信架构(二)

本文详细解析了通信框架中发送请求的基本方式,包括请求的构建、封装及发送过程,以及请求与响应的解析方法。通过实例代码,深入探讨了如何将不同数据类型转换为字节数据进行网络传输,以及请求的组织与处理流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先罗列一小段代码,这一小段代码代表了通信框架中发送请求的基本方式,读者可以根据这段代码,分析整个请求过程:

/** * 典型使用方式: * * StructRequest output = new StructRequest(GameConst.COMM_PRICECOUNT_DATA);//GameConst.COMM_PRICECOUNT_DATA是请求ID,作用有两个:用于服务器端识别请求,用于UI线程解析数据 * * output.writeString("");//请求数据 * * StructRequest output_time = new StructRequest(GameConst.COMM_SERVER_TIME); * * output_time.writeInt(0); * * StructRequest[] temp = { output, output_time }; * * Request request = new Request(temp, this.screenId);//依靠Request对象封装为请求 * * sendRequest(request);//发送请求{这里是耦合点,注意,发送请求的时候,程序的控制类[UI和网络的耦合类]会记录下请求的屏幕ID,用于解析} * * output.cloese();//关闭读写 */

下面罗列StructRequest 类代码,代码中有详细注释,就不多叙述了。

package app.http; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Vector; import app.program.Globe; /** * 功能:把各种类型的数据,转换为字节数组。 * * 属于工具类,为网络连接,本地数据存储提供从其他数据类型到字节数据类型的转换。 * * 注意有些方法中包含了私有项目的网络协议,并没有删除。比如writeInts2中writeLength(v[0].length); */ public class StructRequest { private ByteArrayOutputStream bout; private DataOutputStream out; private int commID; private boolean bTradeCipher; /** * 默认为非加密通讯 * * @param commID * int */ public StructRequest(int commID) { this(); this.commID = commID; bTradeCipher = false; } /** * @param commID * int * @param bTradeCipher * boolean 表示是否需要加密 */ public StructRequest(int commID, boolean bTradeCipher) { this(); this.commID = commID; this.bTradeCipher = bTradeCipher; } public StructRequest() { bout = new ByteArrayOutputStream(); out = new DataOutputStream(bout); } public void writeLength(int v) { writeShort(v); } public void writeBoolean(boolean v) { try { out.writeBoolean(v); } catch (Exception ex) { throw new RuntimeException(); } } public void writeBooleans(boolean[] v) { writeLength(v.length); for (int i = 0; i < v.length; i++) { writeBoolean(v[i]); } } public void writeBooleans2(boolean[][] v) { writeLength(v.length); if (v.length > 0) { writeLength(v[0].length); for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { writeBoolean(v[i][j]); } } } } public void writeByte(int v) { try { out.writeByte(v); } catch (Exception ex) { throw new RuntimeException(); } } public void writeBytes(int[] v) { writeLength(v.length); for (int i = 0; i < v.length; i++) { writeByte(v[i]); } } public void writeBytes2(int[][] v) { writeLength(v.length); if (v.length > 0) { writeLength(v[0].length); for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { writeByte(v[i][j]); } } } } public void writeShort(int v) { try { out.write((v >>> 0) & 0xff); out.write((v >>> 8) & 0xff); } catch (Exception ex) { throw new RuntimeException(); } } public void writeShorts(int[] v) { writeLength(v.length); for (int i = 0; i < v.length; i++) { writeShort(v[i]); } } public void writeShorts2(int[][] v) { writeLength(v.length); if (v.length > 0) { writeLength(v[0].length); for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { writeShort(v[i][j]); } } } } public void writeInt(int v) { try { out.write((v >>> 0) & 0xff); out.write((v >>> 8) & 0xff); out.write((v >>> 16) & 0xff); out.write((v >>> 24) & 0xff); } catch (Exception ex) { throw new RuntimeException(); } } public void writeInts(int[] v) { writeLength(v.length); for (int i = 0; i < v.length; i++) { writeInt(v[i]); } } public void writeInts2(int[][] v) { writeLength(v.length); if (v.length > 0) { writeLength(v[0].length); for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { writeInt(v[i][j]); } } } } private int getSize(int limit) { if (limit >= -128 && limit <= 127) { return 1; } if (limit >= -32768 && limit <= 32767) { return 2; } return 4; } public void writeNumbers(int[] v, int limit) { int size = getSize(limit); writeByte(size); if (size == 1) { writeBytes(v); } else if (size == 2) { writeShorts(v); } else { writeInts(v); } } public void writeNumbers2(int[][] v, int limit) { int size = getSize(limit); writeByte(size); if (size == 1) { writeBytes2(v); } else if (size == 2) { writeShorts2(v); } else { writeInts2(v); } } public void writeLong(long v) { try { out.write(((int) v >>> 0) & 0xff); out.write(((int) v >>> 8) & 0xff); out.write(((int) v >>> 16) & 0xff); out.write(((int) v >>> 24) & 0xff); out.write(((int) v >>> 32) & 0xff); out.write(((int) v >>> 40) & 0xff); out.write(((int) v >>> 48) & 0xff); out.write(((int) v >>> 56) & 0xff); } catch (Exception ex) { throw new RuntimeException(); } } public void writeStringTrade(String v) { try { byte[] tmp = v.getBytes("UTF-8"); out.write(tmp); } catch (Exception ex1) { } } public void writeString(String v) { try { byte[] tmp = v.getBytes("UTF-8"); writeLength(tmp.length); out.write(tmp); } catch (Exception ex1) { } } public void writeStringArray(String[] v) { for (int i = 0; i < v.length; i++) { writeString(v[i]); } } public void writeStrings(String[] v) { writeLength(v.length); for (int i = 0; i < v.length; i++) { writeString(v[i]); } } public void writeStrings2(String[][] v) { writeLength(v.length); for (int i = 0; i < v.length; i++) { writeStrings(v[i]); } } public void writeByteArray(byte[] v) { writeLength(v.length); for (int i = 0; i < v.length; i++) { writeByte(v[i]); } } public void writeByteArray2(byte[] v) { for (int i = 0; i < v.length; i++) { writeByte(v[i]); } } public int getType() { return commID; } /** * 此方法可以实现对程序数据的加密 */ public byte[] getBytes() { if (!bTradeCipher) { return bout.toByteArray(); } else { byte[] data = bout.toByteArray(); for (int i = 0; i < data.length; i++) { data[i] = (byte) (data[i] ^ Globe.key[i % Globe.key.length]); } return data; } } public void writeVector(Vector v) { int num = v.size(); writeLength(num); for (int i = 0; i < num; i++) { writeString((String) v.elementAt(i)); } } public void cloese() { try { if (out != null) { out.close(); } if (bout != null) { bout.close(); } out = null; bout = null; } catch (IOException ex) { } } }

下面罗列Request的代码,注意里面的请求方式分为两种,第一种是一次只请求一种数据,第二种是一次请求多种数据(这种方式有效的减少了请求的次数):

package app.http; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * 功能: * * 把需要发送的内容,再次经过私有协议封装,合并为一个Request对象,并且给这个对象一个和屏幕一致的ID,用于接收和解析数据 * * 其他参照StructRequest */ public class Request { private byte[] content = null; private int screenId = 0; private static final byte START_FLAG = (byte) '{'; private static final byte END_FLAG = (byte) '}'; private static final byte OTHER_FLAG = (byte) ':'; private boolean bTrade = false; /** * 单个通讯 * * @param output * StructOutput */ public Request(StructRequest output, int screeID) { screenId = screeID; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { out.write(START_FLAG); // 标识符 out.write(output.getType() & 0xFF); out.write((output.getType() >>> 8) & 0xFF); out.write(0); out.write(0); out.write(output.getBytes().length & 0xFF); out.write((output.getBytes().length >>> 8) & 0xFF); out.write(output.getBytes()); out.write(END_FLAG); // 校验符 } catch (Exception ex) { } content = out.toByteArray(); try { out.close(); } catch (IOException ex1) { } out = null; } public Request(int screeID) { screenId = screeID; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { out.write(START_FLAG); // 标识符 out.write(0); out.write(0); out.write(0); out.write(0); out.write(0); out.write(0); out.write(END_FLAG); // 校验符 } catch (Exception ex) { } content = out.toByteArray(); try { out.close(); } catch (IOException ex1) { } out = null; } /** * 多个通讯 * * @param output * StructOutput[] */ public Request(StructRequest[] output, int screeID) { screenId = screeID; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { out.write(START_FLAG); // 标识符 for (int i = 0; i < output.length; i++) { out.write(output[i].getType() & 0xFF); out.write((output[i].getType() >>> 8) & 0xFF); out.write(0); out.write(0); out.write(output[i].getBytes().length & 0xFF); out.write((output[i].getBytes().length >>> 8) & 0xFF); out.write(output[i].getBytes()); if (i < output.length - 1) { out.write(OTHER_FLAG); } } out.write(END_FLAG); // 校验符 } catch (Exception ex) { } content = out.toByteArray(); try { out.close(); } catch (IOException ex1) { } out = null; } public int getScreenId() { return screenId; } public byte[] getContent() { return content; } public void sedIsTrade(boolean trade) { this.bTrade = trade; } public boolean getIsTrade() { return this.bTrade; } }

补充说明:在通信的时候,有两种ID,首先是屏幕ID(本文第一段代码中的this.screenId),这个ID用来确定请求的屏幕,以便请求结束以后,由这个屏幕来解析响应。其次是请求ID(本文第一段代码中的GameConst.COMM_PRICECOUNT_DATA)。

为了便于读者理解,下面一段代码展示典型的响应解析方式:

public void httpCompleted(Response resp) { byte[] tmp = resp.getData(GameConst.COMM_DATA);//这里就根据请求ID来解析响应 if (tmp != null) { } }


下一篇讲解请求的发送和响应的接收。

ps:有任何疑问可以留言,回复可能不及时,但是有意义的疑问一定回复。

ps:记得看到好文章好顶……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值