博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MTK socket 小结 4
阅读量:2222 次
发布时间:2019-05-08

本文共 7968 字,大约阅读时间需要 26 分钟。

 

上次说到Demo的socket 链接,先看HTTP请求。

当然要理解这个,得知道一个HTTP请求是什么样子的和HTTP协议的交互过程。要详细了解 可以看 。简单来说,HTTP 协议是请求应答模式,客户端发一个请求,服务器短发一个答复。客户端说:要xxx网页,服务器就把xxx网页返回给你。交互就需要一个规范,这个就是请求和应答的头,比如 请求的第一行: GET /index.html HTTP/1.1 就表示要获得 index.html。(如果要在命令行下模拟,可以输入 telnet  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;    }}
转自:

你可能感兴趣的文章
为什么在优化算法中使用指数加权平均
查看>>
什么是 Q-learning
查看>>
用一个小游戏入门深度强化学习
查看>>
5 分钟入门 Google 最强NLP模型:BERT
查看>>
初探Java设计模式4:一文带你掌握JDK中的设计模式
查看>>
初探Java设计模式5:一文了解Spring涉及到的9种设计模式
查看>>
Java集合详解1:一文读懂ArrayList,Vector与Stack使用方法和实现原理
查看>>
Java集合详解2:一文读懂Queue和LinkedList
查看>>
Java集合详解3:一文读懂Iterator,fail-fast机制与比较器
查看>>
Java集合详解4:一文读懂HashMap和HashTable的区别以及常见面试题
查看>>
Java集合详解5:深入理解LinkedHashMap和LRU缓存
查看>>
Java集合详解6:这次,从头到尾带你解读Java中的红黑树
查看>>
Java集合详解8:Java集合类细节精讲,细节决定成败
查看>>
Java并发指南1:并发基础与Java多线程
查看>>
Java并发指南2:深入理解Java内存模型JMM
查看>>
Java并发指南5:JMM中的final关键字解析
查看>>
Java并发指南6:Java内存模型JMM总结
查看>>
Java并发指南7:JUC的核心类AQS详解
查看>>
Java并发指南8:AQS中的公平锁与非公平锁,Condtion
查看>>
Java网络编程和NIO详解6:Linux epoll实现原理详解
查看>>