转自新浪博客:http://blog.sina.com.cn/s/blog_4cd5d2bb0100fe7y.html
html
公司作了一个小型的wap浏览器的项目,其中涉及到用socket的实现http请求的方法,因为网上相关资料比较少,尤为是详细的资料比较少,因此走了很多弯路。在此仅从实现的角度说明MTK平台用Socket实现HTTP的方法,但愿能给后来者一些微小的帮助。编程
1、MTK平台Socket联网过程
熟悉PC机编程的人都知道,Socket编程接口分两套:TCP和UDP;TCP和UDP中又有服务器端和客户端的概念,这里讲的是TCP的客户端编程接口。windows
MTK平台中Socket建立步骤:浏览器
一、soc_create() 建立Socket;服务器
二、soc_setsockopt 设置Socket为非阻塞模式;网络
三、soc_setsockopt 设置Socket选项为链接,读,写,关闭;不清楚为何要连续设置两次,若有高人路过,请指点;app
四、若是是CMNET联网而且请求中用到了英文域名还须要解析域名soc_gethostbyname,除非使用ip做为域名,解析出来的IP做为咱们创建链接的目标IP;若是是CMWAP联网,直接跳到第5步,直接链接移动或联通的网关:10.0.0.172:80;socket
五、soc_connect与服务器创建链接;jsp
六、soc_send 发送请求;ui
七、soc_recv 接收服务器返回的数据;
八、soc_close 关闭Socket;
九、若是须要关闭数据帐户soc_close_nwk_account
2、CMNET,CMWAP方式下的HTTP请求内容格式
HTTP请求格式:
GET方法
MTK模拟器中wap浏览器发送的请求内容
“GET /go_13596557 HTTP/1.1
Host: kong.net
User-Agent: SQH_D480B_01/LB19504/WAP2.0 Profile
Accept: application/vnd.wap.wmlc, ** //(想当长,省去后面部分)
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方法
对一些须要向服务器传入参数的请求,按名称搜索等请求。还以空中网天气查询为例,之中的其余城市天气查询,输入其余城市名称或电话区号查询:
“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, */* //(想当长,省去后面部分)
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方法没有这一项
××××××//传给服务器46字节长的数据(参数)
“
固然若是是CMWAP联网方式也要和上述的GET方法同样设置Host和X-Online-Host项,Host:10.0.0.172
X-Online-Host: kong.net
以上的内容,能够在调试状态下运行模拟器的wap浏览器,在soc_send方法处插入断点观察。
HTTP的其余方法,因为在应用中没有用到,在这里不作介绍。
3、CMNET,CMWAP链接差异
一、GPRS帐户:
与pc机上的socket客户端接口不一样,手机客户端在soc_create,soc_gethostbyname接口中都多了参数 nwt_acount_id,只的是通常在“网络服务”->“数据帐户”->“GPRS”下的GPRS数据帐户id,通常起始的一个帐户id 是10,往下递增1,在创建链接过程当中,若是是CMWAP方式联网,soc_create,soc_gethostbyname接口就要设置接入点为 CMWAP的帐户id,CMNET就要设置接入点为CMNET的帐户。
二、目标服务器:
还以空中网的天气服务为例,CMNET状况下,soc_connect须要链接”221.179.172.2”这个ip,若是请求的url为”http://kong.net/weather/home.jsp” ,还须要调用soc_gethostbyname接口去解析域名;
若是是CMWAP方式联网,soc_connect只须要链接移动或联动的网关”10.0.0.172:80”。
三、HTTP请求内容格式(或称报文):
如第二节所述。
4、SIM1仍是SIM2联网
SIM1仍是SIM2联网,MTK平台是经过建立socket时传入的nwt_acount_id区分的,若是是SIM1上网,帐号就是指的是通常在“网 络服务”->“数据帐户”->“GPRS”下的对应的GPRS数据帐户id;若是是SIM2,经过在四字节的帐户id其余字节设置掩码来区 分。
设置接口好比07B平台的always_ask_encode_data_account_id,6235_08A的cbm_encode_data_account_id接口。不一样平台可能略有差异。
5、联通卡仍是移动卡?
参考其余Socket联网代码中有的以接入点是否为”uniwap”来判断是否是联通的代理上网,可是经过实验,即便在联通卡时链接移动的”cmwap” 帐户,也是能够正常联网的。不知道设计“GPRS数据帐户”的最初意图是什么?经过apn来区分同一内部ip地址网关不一样的公网ip吗?若有高人路过,请 指点;
6、HTTP1.1与Transfer-Encoding 为chunked的编码方式
发送一个请求后,若是服务器返回的消息头内容包括“Transfer-Encoding: chunked”那么他的传输编码为“chunked”类型。这种传输类型的数据体内容格式是这样:
[16进制数字字符串 1到4个字节 len]\r\n
[len 长的数据体]\r\n
[16进制数字字符串 1到4个字节 len]\r\n
[len 长的数据体]\r\n
[16进制数字字符串 1到4个字节 len == 0]\r\n\r\n
其中,长度len是16进制的数字,表示本段数据体的长度(字节数),回车换行后,就是这一段数据真实内容,这就是一段数据体的格式,一段接一段;直到数 据体长度为0的数据段出现,紧接着两个回车换行,标识本次请求的数据均已接收完毕。不过socket能够根据soc_recv返回值等于0来判断接收数据 结束。若是收到的是这个编码类型的内容,须要对接收到的数据进行处理。
7、MTK平台的S8类型的误导
MTK平台定义的两个数据类型U8和S8,一看名称咱们可能会觉得是unsigned char和signed char,但事实并不是如此,
typedef char S8;
typedef unsigned char U8;
MTK平台的char默认也是unsigned char类型的,soc_gethostbyname返回值类型是kal_int8(typedef signed char kal_int8;),若是S8或平台的char类型是有符号的字符型,那么,kal_int8和S8应该是等价的,但用S8类型变量做为 soc_gethostbyname的返回值时,常常返回254致使域名不会被正常解析,其实应该返回SOC_WOULDBLOCK(-2),应该是阻塞 码,将soc_gethostbyname返回值类型改成kal_int8后,就能正常处理域名解析了。这证实平台的S8类型及char类型默认是无符号 的。
8、不理解的连接错误?
在添加链接超时功能时用到了gui_start_timer和gui_cancel_timer时,没有加入#include "gui.h"时,出现如下连接错误:
Error: L6286E: Value(0x818153e) out of range(-0x400000 - 0x3fffff) for relocation #13 (wrt symbol gui_cancel_timer) in Socket.obj(i. SocDinit)
加上#include "gui.h"时,就没有这个问题,若是程序找不到这个符号,应该是个编译错误,在此为何是个连接错误。
查了一下arm的帮助文档:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3553.html
依然不明白,若是高手路过,请深刻指教一下缘由。