这篇文章讲解真正的网络请求类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();
}
}