一、MTK平臺(tái)Socket聯(lián)網(wǎng)過程
MTK平臺(tái)中Socket創(chuàng)建步驟:
1.建立data account(上網(wǎng)賬號(hào))
MMI層發(fā)送PRT_MMI_PS_SET_GPRS_DATA_ACCOUNT_REQ消息到L4C層,在消息中設(shè)定data account 的id(1-10),自定義名 稱,APN(cmnet,cmwap),用戶名,密碼,DNS等信息.
2、 soc_create() 創(chuàng)建Socket;
kal_int8 soc_create(kal_uint8 domain, socket_type_enum type, kal_uint8 protocol, module_type mod_id, kal_uint32 nwk_account_id);
3、 1 soc_setsockopt 設(shè)置Socket為非阻塞模式;
kal_int8 soc_setsockopt(kal_int8 s, kal_uint16 option, kal_uint8 *val, kal_uint8 val_size);
第二個(gè)參數(shù)option設(shè)置為SOC_NBIO(socket非阻塞模式)
設(shè)置為SOC_ASYNC(異步i/o)
2 soc_setsockopt 設(shè)置Socket選項(xiàng)為連接,讀,寫,關(guān)閉;
val = SOC_READ | SOC_WRITE | SOC_CLOSE | SOC_CONNECT;
soc_setsockopt(socket_id,SOC_NBIO,&val, sizeof(val))
4、 如果是CMNET聯(lián)網(wǎng)并且請(qǐng)求中用到了英文域名還需要解析域名soc_gethostbyname,除非使用ip作為域名,解析出來的IP作為我們建立連接的目標(biāo)IP;如果是CMWAP聯(lián)網(wǎng),直接跳到第5步,直接連接移動(dòng)或聯(lián)通的網(wǎng)關(guān):10.0.0.172:80;
5、 soc_connect與服務(wù)器建立連接;
kal_int8 soc_connect(kal_int8 s, sockaddr_struct *addr);
6、 soc_send 發(fā)送請(qǐng)求;
kal_int32 soc_send(kal_int8 s, kal_uint8 *buf, kal_int32 len, kal_uint8 flags);
其中buf字串需要遵守http連接協(xié)議,例如訪問www.zzmao.com/下的的格式如下:
GET http://www.baidu.com HTTP/1.1
Host:www.baidu.com:80
User-Agent: */*
Accept:*/*
X-Online-Host:www.baidu.com
Connection:Keep-Alive
7、 soc_recv 接收服務(wù)器返回的數(shù)據(jù);
kal_int32 soc_recv(kal_int8 s, kal_uint8 *buf, kal_int32 len, kal_uint8 flags);
buf用來保存接收到的字符串,這里需要注意buf的長(zhǎng)度不能超過2000,否則上真機(jī)的時(shí)候一到申請(qǐng)內(nèi)存空間時(shí)就會(huì)死機(jī),這里我 用循環(huán)來接收信息并寫入文件.
8、 soc_close 關(guān)閉Socket;
kal_int8 soc_close(kal_int8 s);
9、 如果需要關(guān)閉數(shù)據(jù)賬戶soc_close_nwk_account();
其他的一些
10、啟動(dòng)定時(shí)器
void StartTimer(U16 timerid, U32 delay, FuncPtr funcPtr)
在等待服務(wù)器響應(yīng)時(shí)需要用到
11、關(guān)閉定時(shí)器
void StopTimer(U16 timerid)
12. 打開文件
FSAL_Status FSAL_Open(STFSAL *pstFSAL, void *szFile, FSAL_FileMode eMode)
13. 寫文件
FSAL_Status FSAL_Write(STFSAL *pstFSAL, kal_uint8 *pbBuf, kal_uint32 uSize)
14. 關(guān)閉文件
FSAL_Status FSAL_Close(STFSAL *pstFSAL)
15. 回調(diào)函數(shù)
SetProtocolEventHandler(PsFuncPtr funcPtr, U16 eventID)
funcPtr里實(shí)現(xiàn)響應(yīng)socket事件
========================================
soc_error_enum
typedef enum
{
SOC_SUCCESS = 0,
SOC_ERROR = -1,
SOC_WOULDBLOCK = -2,
SOC_LIMIT_RESOURCE = -3, /* limited resource */
SOC_INVALID_SOCKET = -4, /* invalid socket */
SOC_INVALID_ACCOUNT = -5, /* invalid account id */
SOC_NAMETOOLONG = -6, /* address too long */
SOC_ALREADY = -7, /* operation already in progress */
SOC_OPNOTSUPP = -8, /* operation not support */
SOC_CONNABORTED = -9, /* Software caused connection abort */
SOC_INVAL = -10, /* invalid argument */
SOC_PIPE = -11, /* broken pipe */
SOC_NOTCONN = -12, /* socket is not connected */
SOC_MSGSIZE = -13, /* msg is too long */
SOC_BEARER_FAIL = -14, /* bearer is broken */
SOC_CONNRESET = -15, /* TCP half-write close, i.e., FINED */
SOC_DHCP_ERROR = -16,
SOC_IP_CHANGED = -17,
SOC_ADDRINUSE = -18,
SOC_CANCEL_ACT_BEARER = -19 /* cancel the activation of bearer */
} soc_error_enum;
二、CMNET,CMWAP方式下的HTTP請(qǐng)求內(nèi)容格式
HTTP請(qǐng)求格式:
GET方法
MTK模擬器中wap瀏覽器發(fā)送的請(qǐng)求內(nèi)容
“GET /go_13596557 HTTP/1.1
Host: kong.net
User-Agent: SQH_D480B_01/LB19504/WAP2.0 Profile
Accept: application/vnd.wap.wmlc, */* //(想當(dāng)長(zhǎng),省去后面部分)
Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, GB2312, windows-1252, us-ascii
Accept-Language: zh-tw, zh-cn, en
Cookie: JSESSIONID=aAQP0FIXp3z7
Connection: Keep-Alive
“
當(dāng)然模擬器上用的是CMNET,如果是CMWAP,則需要這樣:
“
GET /go_13596557 HTTP/1.1
Host:10.0.0.172
X-Online-Host: kong.net
User-Agent: SQH_D480B_01/LB19504/WAP2.0 Profile
Accept: application/vnd.wap.wmlc, */* //(想當(dāng)長(zhǎng),省去后面部分)
Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, GB2312, windows-1252, us-ascii
Accept-Language: zh-tw, zh-cn, en
Cookie: JSESSIONID=aAQP0FIXp3z7
Connection: Keep-Alive
“
POST方法
對(duì)一些需要向服務(wù)器傳入?yún)?shù)的請(qǐng)求,按名稱搜索等請(qǐng)求。還以空中網(wǎng)天氣查詢?yōu)槔械钠渌鞘刑鞖獠樵儯斎肫渌鞘忻Q或電話區(qū)號(hào)查詢:
“POST /weather/search.jsp?setcity=1 HTTP/1.1
Host: kong.net
User-Agent: SQH_D480B_01/LB19504/WAP2.0 Profile
Accept: application/vnd.wap.wmlc, */* //(想當(dāng)長(zhǎng),省去后面部分)
Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, GB2312, windows-1252, us-ascii
Accept-Language: zh-tw, zh-cn, en
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Cookie: KONG_ACCESS=AWYZhg==; JSESSIONID=a91MDc6qoMYf
Connection: Keep-Alive
Content-Length: 46//get方法沒有這一項(xiàng)
××××××//傳給服務(wù)器46字節(jié)長(zhǎng)的數(shù)據(jù)(參數(shù))
“
當(dāng)然如果是CMWAP聯(lián)網(wǎng)方式也要和上述的GET方法一樣設(shè)置Host和X-Online-Host項(xiàng),Host:10.0.0.172
X-Online-Host: kong.net
以上的內(nèi)容,可以在調(diào)試狀態(tài)下運(yùn)行模擬器的wap瀏覽器,在soc_send方法處插入斷點(diǎn)觀察。
三、CMNET,CMWAP連接差別
1、GPRS賬戶:
與pc機(jī)上的socket客戶端接口不同,手機(jī)客戶端在soc_create,soc_gethostbyname接口中都多了參數(shù)nwt_acount_id,只的是一般在“網(wǎng)絡(luò)服務(wù)”->“數(shù)據(jù)賬戶”->“GPRS”下的GPRS數(shù)據(jù)賬戶id,一般起始的一個(gè)賬戶id是10,往下遞增1,在建立連接過程中,如果是CMWAP方式聯(lián)網(wǎng),soc_create,soc_gethostbyname接口就要設(shè)置接入點(diǎn)為CMWAP的賬戶id,CMNET就要設(shè)置接入點(diǎn)為CMNET的賬戶。
2、目標(biāo)服務(wù)器:
還以空中網(wǎng)的天氣服務(wù)為例,CMNET情況下,soc_connect需要連接”221.179.172.2”這個(gè)ip,如果請(qǐng)求的url為”http://kong.net/weather/home.jsp” ,還需要調(diào)用soc_gethostbyname接口去解析域名;
如果是CMWAP方式聯(lián)網(wǎng),soc_connect只需要連接移動(dòng)或聯(lián)動(dòng)的網(wǎng)關(guān)”10.0.0.172:80”。
3、SIM1還是SIM2聯(lián)網(wǎng)
SIM1還是SIM2聯(lián)網(wǎng),MTK平臺(tái)是通過創(chuàng)建socket時(shí)傳入的nwt_acount_id區(qū)分的,如果是SIM1上網(wǎng),賬號(hào)就是指的是一般在“網(wǎng)絡(luò)服務(wù)”->“數(shù)據(jù)賬戶”->“GPRS”下的對(duì)應(yīng)的GPRS數(shù)據(jù)賬戶id;如果是SIM2,通過在四字節(jié)的賬戶id其他字節(jié)設(shè)置掩碼來區(qū)分。
設(shè)置接口比如07B平臺(tái)的always_ask_encode_data_account_id,6235_08A的cbm_encode_data_account_id接口。不同平臺(tái)可能略有差別。
4、聯(lián)通卡還是移動(dòng)卡???
四、HTTP1.1與Transfer-Encoding 為chunked的編碼方式
發(fā)送一個(gè)請(qǐng)求后,如果服務(wù)器返回的消息頭內(nèi)容包括“Transfer-Encoding: chunked”那么他的傳輸編碼為“chunked”類型。這種傳輸類型的數(shù)據(jù)體內(nèi)容格式是這樣:
[16進(jìn)制數(shù)字字符串 1到4個(gè)字節(jié) len]\r\n
[len 長(zhǎng)的數(shù)據(jù)體]\r\n
[16進(jìn)制數(shù)字字符串 1到4個(gè)字節(jié) len]\r\n
[len 長(zhǎng)的數(shù)據(jù)體]\r\n
[16進(jìn)制數(shù)字字符串 1到4個(gè)字節(jié) len == 0]\r\n\r\n
其中,長(zhǎng)度len是16進(jìn)制的數(shù)字,表示本段數(shù)據(jù)體的長(zhǎng)度(字節(jié)數(shù)),回車換行后,就是這一段數(shù)據(jù)真實(shí)內(nèi)容,這就是一段數(shù)據(jù)體的格式,一段接一段;直到數(shù)據(jù)體長(zhǎng)度為0的數(shù)據(jù)段出現(xiàn),緊接著兩個(gè)回車換行,標(biāo)識(shí)本次請(qǐng)求的數(shù)據(jù)均已接收完畢。不過socket可以根據(jù)soc_recv返回值等于0來判斷接收數(shù)據(jù)結(jié)束。如果收到的是這個(gè)編碼類型的內(nèi)容,需要對(duì)接收到的數(shù)據(jù)進(jìn)行處理。
五
1.實(shí)現(xiàn)之前要規(guī)定好發(fā)送方和接收方數(shù)據(jù)傳輸?shù)膮f(xié)議,數(shù)據(jù)格式.包括如何確定數(shù)據(jù)長(zhǎng)度,校驗(yàn)算法,是否加密等.
2.要注意對(duì)其方式和存儲(chǔ)方式.如果發(fā)送方和接收方的對(duì)其方式和存儲(chǔ)方式不一樣,數(shù)據(jù)可能會(huì)傳輸錯(cuò)誤.
3.錯(cuò)誤處理,確保可以捕捉到所有錯(cuò)誤,從而關(guān)閉socket連接,釋放資源.
4.超時(shí)設(shè)定,由于socket接口沒有提供超時(shí)功能,所以需要自己實(shí)現(xiàn)超時(shí)功能,可在每次操作前設(shè)定timer,如超時(shí)仍沒有收到消息,則進(jìn)行錯(cuò)誤處理,特別要考慮到多個(gè)socket同時(shí)打開的情況.