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

这篇文章讲解真正的网络请求类HttpClient,它负责打开网络链接,获取数据,把数据存放于一个字节数组,让Response解析。

以下是代码:

package app.http; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; import app.program.GameConst; /** * 功能: * * 打开网络链接,获取数据,把数据存放于一个字节数组,让Response解析 */ public class HttpClient { // 注: HttpsConnection继承自HttpConnection private HttpConnection conn = null; private InputStream inputStream = null; private OutputStream outputStream = null; private Request request = null; int msgId; public HttpClient(int _msgId) { msgId = _msgId; } public Response getResponse(Request request) throws Exception { if (request == null) { return null; } try { this.request = request; Response resp = new Response(); // 打开链接 makeConnection(); // 设置参数 setProperty(); // 写入内容 setContent(); // 打开输入流 makeInputStream(); // 得到响应码 resp.responseCode = conn.getResponseCode(); if (resp.responseCode != HttpConnection.HTTP_OK) { return null; } String strContentLength = conn.getHeaderField("content-length"); if (strContentLength != null) { resp.contentLength = Integer.parseInt(strContentLength); } resp.analysisData(readResponse(), true); return resp; } catch (Exception e) { e.printStackTrace(); throw e; } finally { this.request = null; cleanup(); } } private void makeConnection() throws Exception { conn = (HttpConnection) Connector.open("http://", Connector.READ_WRITE, true); } private void makeInputStream() throws Exception { inputStream = conn.openInputStream(); } private void makeOutputStream() throws Exception { outputStream = conn.openOutputStream(); } /** * 参数设置 * * @throws Exception */ private void setProperty() throws Exception { conn.setRequestMethod(HttpConnection.POST); } public void setContent() throws Exception { if (request.getContent() != null) { conn.setRequestProperty("Content-Length", String.valueOf(request.getContent().length)); makeOutputStream(); outputStream.write(request.getContent()); } } /** * 从网络流中读取数据,存放于字节数组中 * * @return * @throws Exception */ private byte[] readResponse() throws Exception { try { byte[] data = null; if (conn != null && inputStream != null) { int len = (int) conn.getLength(); // 读取模式1:直接获取数据长度 if (conn.getRequestMethod().equals(HttpConnection.HEAD)) { return null; } if (len <= 0) { // 读取模式2:从Http连接头获取数据长度 String bodyLength = null; try { bodyLength = conn.getHeaderField("content-length"); } catch (IOException e) { e.printStackTrace(); } if (bodyLength != null) { try { len = Integer.parseInt(conn.getHeaderField("Body-Length")); } catch (Exception e) { e.printStackTrace(); } } } if (len > 0) { int actual = 0; int bytesread = 0; data = new byte[len]; while ((bytesread != len) && (actual != -1)) { actual = inputStream.read(data, bytesread, len - bytesread); if (actual >= 0) { bytesread += actual; } } if (bytesread == 0) { return null; } else if (bytesread < len) { byte[] actualData = new byte[bytesread]; System.arraycopy(data, 0, actualData, 0, bytesread); return actualData; } } else { // 读取模式3:持续读取,直到数据包结束 ByteArrayOutputStream tmp = new ByteArrayOutputStream(); byte[] buffer = new byte[HttpConstants.BUFFER_SIZE]; int count; while ((count = inputStream.read(buffer, 0, HttpConstants.BUFFER_SIZE)) != -1) { tmp.write(buffer, 0, count); } data = tmp.toByteArray(); tmp.close(); tmp = null; buffer = null; } } return data; } catch (Exception e) { e.printStackTrace(); } return null; } public void cleanup() { try { if (inputStream != null) { inputStream.close(); inputStream = null; } if (outputStream != null) { outputStream.close(); outputStream = null; } if (conn != null) { conn.close(); conn = null; } } catch (Exception e) { e.printStackTrace(); } } }


重点关注方法是:

public Response getResponse(Request request) throws Exception;

代码里面涉及了Response和StructResponse,它们的代码页一并罗列:

package app.http; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.EOFException; import java.io.IOException; import java.util.Hashtable; import java.util.Vector; import app.program.Globe; /** * 返回信息的解析方法类,和StructRequest对应 */ public class StructResponse { private DataInputStream in; private ByteArrayInputStream bin; private Hashtable hash; private Vector vec; private int size; public StructResponse(byte[] data) { bin = new ByteArrayInputStream(data); in = new DataInputStream(bin); } public StructResponse(byte[] data, boolean bTradeCipher) { hash = new Hashtable(); vec = new Vector(); if (!bTradeCipher) { readTradeData(data); } else { readTradeCipherData(data); } this.getTable(); } private boolean bTable = false; private int tableIndex = 0; // 表格数据的列数 private void readTradeData(byte[] data) { int i = 0; try { for (; i < data.length; i++) { if (data[i] == 0x01) { String s = new String(data, 0, i, "UTF-8"); if (bTable) { vec.addElement(s); if (tableIndex == 0) { tableIndex = vec.size(); } } else { putInHash(s); } break; } else if (data[i] == 0x02) { String s = new String(data, 0, i, "UTF-8"); if (bTable) { vec.addElement(s); } else { putInHash(s); } break; } else if (data[i] == 0x03) { bTable = true; if (i > 0) { String s = new String(data, 0, i, "UTF-8"); putInHash(s); } break; } else if (data[i] == 0x04) { bTable = false; String s = new String(data, 0, i, "UTF-8"); vec.addElement(s); if (tableIndex == 0) { tableIndex = vec.size(); } break; } } String s = new String(data, 0, i, "UTF-8"); putInHash(s); } catch (Exception ex) { ex.printStackTrace(); } if (data.length - i - 1 > 0) { byte[] nData = new byte[data.length - i - 1]; System.arraycopy(data, i + 1, nData, 0, data.length - i - 1); readTradeData(nData); } } private void readTradeCipherData(byte[] data) { for (int i = 0; i < data.length; i++) { data[i] = (byte) (data[i] ^ Globe.key[i % Globe.key.length]); } readTradeData(data); } private void putInHash(String s) { int index = s.indexOf("="); if (index >= 0) { String s1 = s.substring(0, index); String s2 = s.substring(index + 1, s.length()); this.hash.put(s1, s2); } } public String getHashData(String key) { return (String) hash.get(key); } public String[][] getTable() { if (tableIndex <= 0) { return null; } int line = vec.size() / this.tableIndex; String[][] tmp = new String[line][tableIndex]; for (int i = 0; i < line; i++) { for (int j = 0; j < tableIndex; j++) { tmp[i][j] = (String) vec.elementAt(i * tableIndex + j); } } return tmp; } public int readLength() { size = readShort(); return size; } public int getSize() { return size; } public boolean readBoolean() { try { return in.readBoolean(); } catch (Exception ex) { throw new RuntimeException(); } } public boolean[] readBooleans() { boolean[] v = new boolean[readLength()]; for (int i = 0; i < v.length; i++) { v[i] = readBoolean(); } return v; } public boolean[][] readBooleans2() { int length = readLength(); if (length == 0) { return new boolean[0][]; } boolean[][] v = new boolean[length][readLength()]; for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { v[i][j] = readBoolean(); } } return v; } public int readByte() { try { return in.readByte(); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(); } } public int[] readBytes() { int[] v = new int[readLength()]; for (int i = 0; i < v.length; i++) { v[i] = readByte(); } return v; } public int[][] readBytes2() { int length = readLength(); if (length == 0) { return new int[0][]; } int[][] v = new int[length][readLength()]; for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { v[i][j] = readByte(); } } return v; } public int readShort() { try { int v2 = in.read(); int v1 = in.read(); if ((v1 | v2) < 0) { throw new EOFException(); } return ((v1 << 8) + (v2 << 0)); } catch (IOException ex) { return 0; } } public int[] readShorts() { int[] v = new int[readLength()]; for (int i = 0; i < v.length; i++) { v[i] = readShort(); } return v; } public int[][] readShorts2() { int length = readLength(); if (length == 0) { return new int[0][]; } int[][] v = new int[length][readLength()]; for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { v[i][j] = readShort(); } } return v; } public int readInt() { try { int v4 = in.read();// dd int v3 = in.read();// b4 int v2 = in.read();// 4 int v1 = in.read();// 0 if ((v1 | v2 | v3 | v4) < 0) { throw new EOFException(); } return ((v1 << 24) + (v2 << 16) + (v3 << 8) + (v4 << 0)); } catch (IOException ex) { return 0; } } public int[] readInts() { int[] v = new int[readLength()]; for (int i = 0; i < v.length; i++) { v[i] = readInt(); } return v; } public int[][] readInts2() { int length = readLength(); if (length == 0) { return new int[0][]; } int[][] v = new int[length][readLength()]; for (int i = 0; i < v.length; i++) { for (int j = 0; j < v[0].length; j++) { v[i][j] = readInt(); } } return v; } public int[] readNumbers() { int size = readByte(); if (size == 1) { return readBytes(); } if (size == 2) { return readShorts(); } return readInts(); } public int[][] readNumbers2() { int size = readByte(); if (size == 1) { return readBytes2(); } if (size == 2) { return readShorts2(); } return readInts2(); } public long readLong() { try { int v8 = in.read(); int v7 = in.read(); int v6 = in.read(); int v5 = in.read(); int v4 = in.read(); int v3 = in.read(); int v2 = in.read(); int v1 = in.read(); if ((v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8) < 0) { throw new EOFException(); } return ((v1 << 56) + (v2 << 48) + (v3 << 40) + (v4 << 32) + (v5 << 24) + (v6 << 16) + (v7 << 8) + (v8 << 0)); } catch (IOException ex) { return 0; } } public String readString() { try { int len = readLength(); byte[] b = new byte[len]; in.read(b); return new String(b, "UTF-8"); } catch (IOException ex) { return null; } } public String[] readStrings() { String[] v = new String[readLength()]; for (int i = 0; i < v.length; i++) { v[i] = readString(); } return v; } public String[][] readStrings2() { String[][] v = new String[readLength()][]; for (int i = 0; i < v.length; i++) { v[i] = readStrings(); } return v; } public byte[] readByteArray() { byte[] v = new byte[readLength()]; for (int i = 0; i < v.length; i++) { v[i] = (byte) readByte(); } return v; } public byte[] getOthers() { try { int num = in.available(); byte[] tmp = new byte[num]; for (int i = 0; i < num; i++) { tmp[i] = in.readByte(); } return tmp; } catch (IOException ex) { return null; } } public Vector readVector() { int num = readLength(); Vector v = new Vector(num); for (int i = 0; i < num; i++) { v.addElement(readString()); } return v; } public void cloese() { try { if (in != null) { in.close(); } if (bin != null) { bin.close(); } in = null; bin = null; } catch (IOException ex) { } } }


package app.http; import java.util.Hashtable; import java.io.*; /** * 按照私有协议,解析数据,和Request对应,把最终解析结果存放于一个hash中,存放格式是 消息码--消息内容 */ public class Response { private Hashtable hash = new Hashtable(); public int responseCode; public int contentLength; private static final byte START_FLAG = (byte) '{'; private static final byte END_FLAG = (byte) '}'; private static final byte OTHER_FLAG = (byte) ':'; public Response() { } /** * 分析数据 解析TYPE和真正数据content * * @param data * byte[] */ public void analysisData(byte[] _data, boolean isStart) { StructResponse struct = new StructResponse(_data); byte[] data = null; try { while (isStart) { int v = struct.readByte(); if (v == -1) { throw new IOException(" DATA"); } if (v == START_FLAG) { break; } } int type = struct.readShort(); struct.readByte(); // 0 标志位 struct.readByte(); // 0 标志位 data = struct.readByteArray(); byte tmp = (byte) struct.readByte(); if (tmp == END_FLAG) { hash.put(Integer.toString(type), data); } else if (tmp == OTHER_FLAG) { hash.put(Integer.toString(type), data); analysisData(struct.getOthers(), false); } else { throw new IOException("BAD DATA"); } } catch (IOException ex) { ex.printStackTrace(); } } public int getResponseCode() { return responseCode; } public int getContentLength() { return contentLength; } public byte[] getData(int key) { return (byte[]) hash.get(Integer.toString(key)); } public int getResponseNum() { return hash.size(); } }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值