您的位置:首页 > 其它

MTK socket 小结 5

2010-11-01 17:37 225 查看
很久没有跟新了,自己的承诺都没有兑现,对不起各位关注支持我的,更对不起自己。对于有些问题,没有回答的话,麻烦你再提一下,我找不清楚哪些回答了,sorry。
上次说到Demo的socket 链接,先看HTTP请求。
当然要理解这个,得知道一个HTTP请求是什么样子的和HTTP协议的交互过程。要详细了解 可以看 RFC 标准文档。简单来说,HTTP 协议是请求应答模式,客户端发一个请求,服务器短发一个答复。客户端说:要xxx网页,服务器就把xxx网页返回给你。交互就需要一个规范,这个就是请求和应答的头,比如 请求的第一行: GET /index.html HTTP/1.1 就表示要获得 index.html。(如果要在命令行下模拟,可以输入 telnet www.baidu.com 80 , 链接成功后,输入 GET / HTTP/1.1 回车回车,就能获得baidu首页了,这个过程就是模拟了想服务器发送了一个最简单的HTTP 请求)
简单过程分析如下:
1 分析URL 把域名,请求地址,和 端口 拆分开
2 进行域名解析,也就是把网址解析成ip地址,这个是异步的过程
3 等解析完成之后,对这个ip地址进行链接
4 链接成功,组装HTTP 请求 头,发送数据
5 如果发送成功,那么一会就会收到通知,有数据可读
6 收到可读消息后,读取内容。
7 交互完成,关闭socket
具体代码分析:
int en_soc_demo_http_send_request(void)
{
// 是否初始化
if (soc_demo_transaction)
{
// 当前状态, HTTP_DNS_QUERY 表示第一步需要域名解析
if (soc_demo_transaction->state == HTTP_DNS_QUERY &&
(soc_demo_app_http_url_struct*) soc_demo_transaction->url_parsed_info == NULL)
{
// 解析URL,主要是把域名,请求地址,端口区分出来
// 比如 http://blog.csdn.net/yanwuxufeng 域名是 http://blog.csdn.net // 请求地址是yanwuxufeng ,端口默认是 80
soc_demo_transaction->url_parsed_info =
(soc_demo_app_http_url_struct*) en_soc_demo_http_get_parsed_url(
soc_demo_transaction->url,
soc_demo_transaction->url_len);
if (soc_demo_transaction->url_parsed_info)
{
// 根据域名,获取域名的ip地址
// 这是个异步的过程,回调函数得到结果
(void)en_soc_demo_get_host_by_name(
HTTP,
(kal_uint8*) soc_demo_transaction->url_parsed_info->host_name);
return EN_SOC_SUCCESS;
}
else
{
en_soc_output_result(EN_SOC_INVAL_PARA, NULL, 0);
return EN_SOC_INVAL_PARA;
}
}
// 解析完ip地址,就可以封装HTTP 请求头,然后发送
else if (soc_demo_transaction->state == HTTP_TCP_CON_CREATING)
{
kal_int8 ret;

char CRLF[3] = {0x0d, 0x0a, 0x00};
soc_demo_transaction->state = HTTP_TCP_CON_CREATED;
/* Create HTTP Get Message */

// 设置HTTP 请求方法
soc_demo_transaction->snd_data_len = 0;
strcat(soc_demo_transaction->snd_buffer, "GET ");
soc_demo_transaction->snd_data_len += 4;

// 设置请求 URI
if (soc_demo_transaction->url_parsed_info->url_link)
{
strcat(
(char*)soc_demo_transaction->snd_buffer,
(char*)soc_demo_transaction->url_parsed_info->url_link);
soc_demo_transaction->snd_data_len += soc_demo_transaction->url_parsed_info->url_link_len;

strcat((char*)soc_demo_transaction->snd_buffer, " ");
soc_demo_transaction->snd_data_len += 2;
}
else
{
// 没有就是根目录,
strcat((char*)soc_demo_transaction->snd_buffer, "/ ");
soc_demo_transaction->snd_data_len += 2;
}

// 设置协议版本
strcat((char*)soc_demo_transaction->snd_buffer, "HTTP/1.1");
soc_demo_transaction->snd_data_len += 8;

// 第一行结束,加上 换行符
strcat((char*)soc_demo_transaction->snd_buffer, CRLF);
soc_demo_transaction->snd_data_len += 2;

// 设置主机,在cmwap 请求是,这个是必须的
strcat((char*)soc_demo_transaction->snd_buffer, "Host: ");
soc_demo_transaction->snd_data_len += 6;

//主机域名
strcat((char*)soc_demo_transaction->snd_buffer, (char*)soc_demo_transaction->url_parsed_info->host_name);
soc_demo_transaction->snd_data_len += soc_demo_transaction->url_parsed_info->host_name_len;

strcat((char*)soc_demo_transaction->snd_buffer, CRLF);
soc_demo_transaction->snd_data_len += 2;

strcat((char*)soc_demo_transaction->snd_buffer, "Connection: Closed");
soc_demo_transaction->snd_data_len += 18;

strcat((char*)soc_demo_transaction->snd_buffer, CRLF);
soc_demo_transaction->snd_data_len += 2;

strcat((char*)soc_demo_transaction->snd_buffer, CRLF);
soc_demo_transaction->snd_data_len += 2;

soc_demo_transaction->server_ip_addr.port = soc_demo_transaction->url_parsed_info->ser_port_num;

// 进行链接
ret = soc_connect(soc_demo_transaction->socket_id, &soc_demo_transaction->server_ip_addr);

// 链接成功,进行下一步动作
if (ret == SOC_SUCCESS)
{
en_soc_demo_http_send_request();
return EN_SOC_SUCCESS;
}
// 如果是block,那么进行等待,等到消息的返回
else if (ret == SOC_WOULDBLOCK)
{
mmi_frm_set_protocol_event_handler(MSG_ID_APP_SOC_NOTIFY_IND, (PsIntFuncPtr)em_soc_demo_app_socket_notify, MMI_TRUE);
return EN_SOC_SUCCESS;
}
else
{
// 错误
if (ret == SOC_ERROR)
{
en_soc_output_result(EN_SOC_PEER_NOT_REACHABLE, NULL, 0);
return EN_SOC_PEER_NOT_REACHABLE;
}
else
{
en_soc_output_result(EN_SOC_ERROR, NULL, 0);
return EN_SOC_ERROR;
}
}
}
// 链接成功之后,可以发送数据
else if (soc_demo_transaction->state == HTTP_TCP_CON_CREATED || soc_demo_transaction->state == REQ_SEND_RETRY ||
soc_demo_transaction->state == REQ_SENDING)
{
kal_int32 ret;

// 第一次发送,
if (soc_demo_transaction->state != REQ_SENDING)
{
soc_demo_transaction->snd_counter = 0;
}
soc_demo_transaction->state = REQ_SENDING;

// 发送数据
ret = soc_send(
soc_demo_transaction->socket_id,
(kal_uint8*) (soc_demo_transaction->snd_buffer + soc_demo_transaction->snd_counter),
(soc_demo_transaction->snd_data_len - soc_demo_transaction->snd_counter),
0);

if (ret > 0)
{
// 发送完毕
// 其实这里有个bug
// 应该是 if ((soc_demo_transaction->snd_counter + ret) == (kal_int32) soc_demo_transaction->snd_data_len)
// 因为数据量很小,几乎不问题.

if (ret == (kal_int32) soc_demo_transaction->snd_data_len)
{
soc_demo_transaction->state = REQ_SENT;
soc_demo_transaction->post_retry_counter++;
em_soc_demo_app_start_timer();  /* wait for servwer's response */
en_soc_demo_tcp_app_recv_response();
return EN_SOC_SUCCESS;
}
else
{
// 发送了一部分,需要继续发送
soc_demo_transaction->snd_counter += ret;
return EN_SOC_SUCCESS;
}
}
else
{
// bloc 状态,需要等待,直道可以发送
if (ret == SOC_WOULDBLOCK)
{
/* waits for socket notify */
mmi_frm_set_protocol_event_handler(MSG_ID_APP_SOC_NOTIFY_IND, (PsIntFuncPtr)em_soc_demo_app_socket_notify, MMI_TRUE);
return EN_SOC_SUCCESS;
}
else
{
if (ret == SOC_ERROR)
{
en_soc_output_result(EN_SOC_PEER_NOT_REACHABLE, NULL, 0);
return EN_SOC_PEER_NOT_REACHABLE;
}
else
{
en_soc_output_result(EN_SOC_ERROR, NULL, 0);
return EN_SOC_ERROR;
}
}
}
}
else
{
en_soc_output_result(EN_SOC_ERROR, NULL, 0);
return EN_SOC_ERROR;
}
}
else
{
en_soc_output_result(EN_SOC_ERROR, NULL, 0);
return EN_SOC_ERROR;
}
}


 

 

写的不多,有点晚了,待续。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: