//當(dāng)前只能由一個線程使用singleton。
private static NetConnection singleton = new NetConnection();
private static HttpConnection httpConn;
private static String url;
private static String method;
private static byte[] data;
private static String contentType;
private static long lowRange;
private static long highRange;
private static boolean disableProxy;
private static boolean detached;
private static byte[] response;
//線程run方法
public void run()
//當(dāng)前運(yùn)行的線程執(zhí)行完畢后,通報(bào)給其它的由于等待資源而wait狀態(tài)的線程
private synchronized void forceNotify()
//當(dāng)資源正在被其它線程使用時,當(dāng)前線程進(jìn)入wait狀態(tài)
private synchronized void forceWait()
//關(guān)閉http連接
private static void severConnection()
/**
* 實(shí)現(xiàn)了連接邏輯。
* 調(diào)用者可以在分離的線程中使用netConnection類的靜態(tài)連接。
* @throws IllegalStateException 如果此方法直接其它類調(diào)用則拋出該異常
*/
public void run() {
if (url == null) {
throw new IllegalStateException("Cannot invoke this method!");
}
DataOutputStream dos = null;
DataInputStream dis = null;
StringBuffer buffer = null;
try {
int permissions = 0;
//根據(jù)method值,設(shè)置Connector的權(quán)限(READ/READ_WRITE)
if (HttpConnection.GET.equals(method)) {
permissions = Connector.READ;
} else if (HttpConnection.POST.equals(method)) {
permissions = Connector.READ_WRITE;
}
//如果關(guān)閉server代理功能,則構(gòu)造noProxyUrl。
//原理:使用timestamp作為該URL中no-proxy參數(shù)值,
// 致使server視其為client發(fā)來的新請求。
if (disableProxy) {
boolean hasQueryParams = false;
char[] ca = url.toCharArray();
//判斷原URL中是否含有參數(shù)
for (int loop = 0; loop < url.length(); loop++) {
if (ca[loop] == '?') {
hasQueryParams = true;
break;
}
}
//由于需要多次字符串拼接,所以使用可提供效率的StringBuffer類
StringBuffer noProxyUrl = new StringBuffer();
//將原URL內(nèi)容復(fù)制到noProxyUrl
noProxyUrl.append(url);
//如果原URL中含有參數(shù),
// 則需要在noProxyUrl中增加"&",
// 否則直接在noProxyUrl中增加"?",
// 這樣做為了后面增加no-proxy參數(shù)做準(zhǔn)備。
if (hasQueryParams) {
noProxyUrl.append("&");
} else {
noProxyUrl.append("?");
}
//增加no-proxy參數(shù)
noProxyUrl.append("no-proxy=");
noProxyUrl.append(System.currentTimeMillis()); // timestamp
//將構(gòu)造好的noProxyUrl復(fù)制到原URL
url = noProxyUrl.toString();
}
// 打開Http 連接
httpConn = (HttpConnection) Connector.open(url, permissions, true);
//設(shè)置request方法
httpConn.setRequestMethod(method);
//如果request權(quán)限為READ(即request方法為GET),
//則需要設(shè)置http request屬性的Range。
//原理:設(shè)置http request屬性的Range后的,
// server接收到該request后將把response數(shù)據(jù)分成小部分發(fā)回。
// 從而避免了部分運(yùn)營商對http response size的限制。
if (permissions == Connector.READ) {
if (lowRange > -1 && lowRange < highRange) {
StringBuffer range = new StringBuffer();
range.append("bytes=");
range.append(lowRange);
range.append("-");
range.append(highRange);
httpConn.setRequestProperty("Range", range.toString());
}
//否則,request權(quán)限為READ_WRITE(即request方法為POST),
//那么設(shè)置request的Content-Type屬性。
} else if (permissions == Connector.READ_WRITE) {
// POST request
httpConn.setRequestProperty("Content-Type", contentType);
dos = httpConn.openDataOutputStream();
dos.write(data);
}
} catch (Exception e) {
exceptionPipe = e;
//如果程序運(yùn)行在多線程模式,則在異常發(fā)生后需要喚醒其它睡眠的線程繼續(xù)run
if (detached) {
forceNotify();
}
return;
} finally {
try {
try {
if (dos != null) {
// 關(guān)閉dos
dos.close();
}
} catch (Exception e) {
// 如果程序運(yùn)行在多線程模式,則在異常發(fā)生后需要喚醒其它睡眠的線程繼續(xù)run
if (exceptionPipe == null) {
exceptionPipe = e;
if (detached) {
forceNotify();
}
return;
}
} finally {
dos = null;
}
// 讀取http連接的回應(yīng)代碼
int responseCode = httpConn.getResponseCode();
//當(dāng)request方法為GET,并設(shè)置了request range時,接收到的回應(yīng)代碼為HTTP_PARTIAL
//當(dāng)request方法為POST,接收到的回應(yīng)代碼為HTTP_OK
//如果上述兩種回應(yīng)代碼均沒有收到,則表明連接失敗或者出問題
if (responseCode != HttpConnection.HTTP_OK
&& responseCode != HttpConnection.HTTP_PARTIAL) {
if (exceptionPipe == null) {
StringBuffer errorCode = new StringBuffer();
errorCode.append("Response code from server: ");
errorCode.append(responseCode);
errorCode.append("/nMessage: [");
errorCode.append(httpConn.getResponseMessage());
errorCode.append("]");
exceptionPipe = new IOException(errorCode.toString());
if (detached) {
forceNotify();
}
return;
}
}
//如果收到了上述的兩種回應(yīng)代碼之一,則可以繼續(xù)讀取server的response數(shù)據(jù)
dis = httpConn.openDataInputStream();
//循環(huán)讀取repsonse數(shù)據(jù)
int ch;
buffer = new StringBuffer();
while ((ch = dis.read()) != -1) {
buffer.append((char) ch);
}
//將response數(shù)據(jù)進(jìn)行必要的編碼轉(zhuǎn)換
response = buffer.toString().getBytes("ISO8859_1");
//接收到回應(yīng)后,表明整個http會話過程結(jié)束,線程將結(jié)束。
//如果程序運(yùn)行在多線程模式,則此時需要喚醒其它睡眠的線程繼續(xù)run
if (detached) {
forceNotify();
}
return;
} catch (Exception e) {
if (exceptionPipe == null) {
exceptionPipe = e;
if (detached) {
forceNotify();
}
return;
}
} finally {
try {
if (dis != null) {
// 關(guān)閉dis
dis.close();
}
} catch (Exception e) {
// 若關(guān)閉dis時發(fā)生異常,則進(jìn)行異常處理
if (exceptionPipe == null) {
exceptionPipe = e;
if (detached) {
forceNotify();
}
return;
}
} finally {
dis = null;
}
try {
if (httpConn != null) {
//關(guān)閉http連接
httpConn.close();
httpConn = null;
}
} catch (Exception e) {
if (exceptionPipe == null) {
exceptionPipe = e;
if (detached) {
forceNotify();
}
return;
}
}
}
}
}
(出處:http://m.survivalescaperooms.com)
|
新聞熱點(diǎn)
疑難解答
圖片精選