中國移動 GPRS 網路提供兩種 APN 接入點:CMNET (公網直連) 與 CMWAP (WAP 閘道代理)。不同廠牌手機預設接入點不同,導致 J2ME 應用網路連線相容性問題。本文詳細分析兩種接入點特性並提供雙模相容程式碼。
public byte[] downloadCMNET(String url) {
HttpConnection conn = null;
InputStream is = null;
try {
conn = (HttpConnection) Connector.open(
"https://" + SERVER_HOST + "/" + url, Connector.READ, true);
is = conn.openInputStream();
int len = (int) conn.getLength();
byte[] data;
if (len == -1) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch;
while ((ch = is.read()) != -1) bos.write(ch);
data = bos.toByteArray();
bos.close();
} else {
data = new byte[len];
readFully(is, data, 0, len);
}
return data;
} catch (IOException e) {
return null;
} finally {
closeQuietly(is);
closeQuietly(conn);
}
}
X-Online-Host 標頭指定真實目標主機public byte[] downloadCMWAP(String url) {
HttpConnection conn = null;
InputStream is = null;
try {
// 連線至 WAP 閘道,路徑帶入目標 URL
conn = (HttpConnection) Connector.open(
"https://10.0.0.172:80/" + url, Connector.READ, true);
// 關鍵:告知閘道真實目標主機
conn.setRequestProperty("X-Online-Host", SERVER_HOST);
conn.setRequestProperty("Accept", "*/*");
is = conn.openInputStream();
int len = (int) conn.getLength();
byte[] data;
if (len == -1) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch;
while ((ch = is.read()) != -1) bos.write(ch);
data = bos.toByteArray();
bos.close();
} else {
data = new byte[len];
readFully(is, data, 0, len);
}
return data;
} catch (IOException e) {
return null;
} finally {
closeQuietly(is);
closeQuietly(conn);
}
}
public byte[] download(String url) {
// 1. 嘗試 CMNET (直連)
byte[] data = downloadCMNET(url);
if (data != null) return data;
// 2. 失敗則嘗試 CMWAP (代理)
return downloadCMWAP(url);
}
// 輔助方法
private void readFully(InputStream is, byte[] buf, int off, int len) throws IOException {
int total = 0;
while (total < len) {
int read = is.read(buf, off + total, len - total);
if (read == -1) break;
total += read;
}
}
private void closeQuietly(Connection c) {
if (c != null) try { c.close(); } catch (IOException ignore) {}
}
若不想在程式碼處理雙模,可引導使用者設定:
| 特性 | CMNET | CMWAP |
|---|---|---|
| APN | cmnet | cmwap |
| Proxy | 無 | 10.0.0.172:80 |
| 目標主機標頭 | Host | X-Online-Host |
| 支援協定 | TCP/UDP/HTTP/HTTPS | 僅 HTTP/HTTPS |
| 埠號限制 | 無 | 通常限 80/443 |
| 適用裝置 | Nokia、Sony Ericsson 等 | Motorola、部分國產機 |
Connector.open(..., true) 啟用逾時機制getLength() 在部分 Nokia S60 回傳 -1,必須備妥分塊讀取邏輯開發階段可使用 WTK 模擬器配合網路監控工具 (如 Wireshark) 驗證封包路徑。上線前務必在真實移動網路環境下,以不同品牌手機進行實測。
掌握 CMNET/CMWAP 雙模開發技巧,能讓您的 J2ME 應用覆蓋絕大多數中國移動用戶,避免因接入點差異導致的連線失敗。