在MT2503上如何用socket 实现联网

关键字 :MT2503socket

随着终端用户需求的改变,要求支持越来越多的网络应用,而MT2503平台提供了一系列的socket  API,开发者可以调用这些API,来实现终端跟网络、服务器之间的数据交互,包括数据的发送、接收等。


1、基本概念
(1).    Data account(数据账户)
每一个联网的应用都需要设置相关的data account。在建立网络连接时,通过设置的data account id获取联网一些配置信息。
data account id中的信息包括app id,sim id,origin account id,always ask信息。
app id:用于标志特定联网的app。
Sim id:联网的sim卡信息,也就是现在具体是用哪个sim卡在上网。
Origin account id:原始的account id,也就是在数据帐户菜单中对应的apn 的id。
Always_ask信息:在应用联网之前是否需要弹出一个PopUp,让用户去选择现在联网应用要使用的data account,一般设置为False。

(2).    非阻塞和异步模式
阻塞模式:socket发出request后,如果没有收到response不会返回任何response 给应用,这种case 下,应用需要阻塞直到收到response。
非阻塞模式:soc发出request后,不管有沒有收到reponse都返回response 给应用。
非阻塞加异步:soc发出request后,如果没有收到response,返回SOC_WOULDBLOCK,当response到来时,上报MSG_ID_APP_SOC_NOTIFY_IND给应用。

(3).    终端跟server 的通讯协议
socket连接建立以后,要与server进行数据的交互,而两者发送的数据必须是基于同一种协议才能保证可以正常通讯。一般比较常见的是http request & http response。

一个简单的http request如下,以www.baidu.com为例
GET / HTTP/1.1
Host: www.baidu.com
Connection: close
以上的http request就是一个简单的获取www.baidu.com网页内容的http request。
在收到http request之后,server端会返回http response。一般情况下,如果返回的数据里面包含
HTTP/1.1 200 OK 字段,就表明server端成功接收到了终端发给它的数据,并做了回应。

2、Socket编程的步骤
(1).注册appid, 
(2).encode一个data account id。
(3).soc_create,返回值为收发数据的时候用的socket id。
(4).soc_setsockopt,设置socket为异步和非阻塞模式。
(5).soc_gethostbyname,通过查询server的域名,获得server的ip地址。
(6).soc_connect,连接server的ip地址。
(7).soc_send,向server发送数据(这里以http request为例)。
(8).soc_recv,接收server端的数据(也就是http response)。
(9).soc_close,数据交互完成,关闭socket。


需要说明的是:

(1)、如果连接是以通过proxy 的方式实现的,不需要步骤5,但是步骤6中需要直接连接代理服务器的ip地址,之后通过代理服务器,与server进行数据的交互。

(2)、如果当前工程是modem工程,则需要改变获取data account id和处理notify消息的方式。

3、sample code

/******************************************Global variable start******************/
Static kal_int8 socket_id;
Static kal_uint8 app_id=0;
Static kal_uint32 account_id=CBM_DEFAULT_ACCT_ID;
Static sockaddr_struct g_test_ip;
Kal_char* recv_buf;
/******************************************Global variable end******************/
/*******************************create and connect my socket start*****************/
Void my_socket_create()
{
    cbm_app_info_struct info;                        
    kal_uint8 val_async;                            //设置socket为异步的val值
    kal_bool val_nonblocking=KAL_TRUE;                //设置socket为非阻塞的val值
    kal_char dest[]=”www.baidu.com”;
    kal_uint8* recvaddr=NULL;
    kal_uint8 addr_len ;
    kal_int8 ret_domain=SOC_ERROR;
    kal_int8 ret_connect=SOC_ERROR;
    recvaddr = OslMalloc(5);
    memset(recvaddr,0,sizeof(recvaddr));
    memset(&g_test_ip,0,sizeof(g_test_ip));
    If(app_id==0)
    {
        memset(&info,0,sizeof(info));                    //初始化info
        info.app_str_id = STR_SOCKET_TEST;            //自己定义的字串
        info.app_icon_id = IMG_SOCKET_TEST;            //自己定义的icon
        info.app_type = DTCNT_APPTYPE_EMAIL; //通过smart原则,匹配apn为cmnet的data account
        cbm_register_app_id_with_app_info(&info,&app_id);        //注册app id
        account_id=cbm_encode_data_account_id(account_id,0,app_id,KAL_FALSE);//encode data account id(数据账户id)
    }
    If(app_id == 0)
    {
        return ;
    }
    mmi_frm_set_protocol_event_handler(MSG_ID_APP_SOC_GET_HOST_BY_NAME_IND,(PsIntFuncPtr)my_socket_get_host_by_name,MMI_TRUE);

    //注册域名解析的notify处理函数
    mmi_frm_set_protocol_event_handler(MSG_ID_APP_SOC_NOTIFY_IND,(PsIntFuncPtr)my_socket_notify,MMI_TRUE);

    //注册异步的socket option选项相关的notify处理函数
    socket_id = soc_create(SOC_PF_INET,SOC_SOCK_STREAM,0,MOD_MMI, account_id);//创建socket id
    if(socket_id < 0)
    {
        soc_close(socket_id);    

        return ;
    }
    If(soc_setsockopt(socket_id,SOC_NBIO, &val_nonblocking,sizeof(val_nonblocking))<0)//设置socket选项为非阻塞
    {
        soc_close(socket_id);    

        return ;
    }
    val_async = SOC_WRITE | SOC_READ|SOC_CONNECT | SOC_CLOSE;//设置socket选项为异步
    If(soc_setsockopt(socket_id,SOC_ASYNC, & val_async,sizeof(val_async))<0)
    {
        soc_close(socket_id);    return ;
    }
    ret_domain=soc_gethostbyname(KAL_FALSE,MOD_MMI,1,dest,recvaddr,& addr_len,0, account_id);                 //对目标域名进行解析,获得目标server的ip。
    If(ret_domain == SOC_SUCCESS)
    {
        memcpy(g_test_ip.addr,recvaddr,addr_len); //将域名解析得到的ip保存到结构体中
        g_test_ip.addr_len = addr_len;            //地址长度
        g_test_ip.port = 80;                    //端口
        g_test_ip.sock_type = SOC_SOCK_STREAM;        //socket type为tcp
        ret_connect = soc_connect(socket_id,&g_test_ip);    //与服务器建立连接
        if(ret_connect == SOC_SUCCESS)
        {
            my_socket_send();                            //连接成功送http request
        }
        else if(ret_connect != SOC_WOULDBLOCK)            //连接失败
        {
            soc_close(socket_id);    

            return ;
        }
    }
    else if(ret_domain != SOC_WOULDBLOCK)                //域名解析失败
    {
        soc_close(socket_id);   

        return ;

    }
}
/***********************************create my socket end*****************/
/***********************************send http request start*****************/
void my_socket_send()
{
    Kal_int32 ret_send=0;
    Kal_char CRLF[] = {0x0d,0x0a,0x00};
    Kal_char send_buf[80]={0};
    memset(send_buf,0,sizeof(send_buf));
    strcat(send_buf,”GET / HTTP/1.1“);
    strcat(send_buf,CRLF);
    strcat(send_buf,”Host: www.baidu.com “);    
    strcat(send_buf,CRLF);
    strcat(send_buf,”Connection: Closed”);
    strcat(send_buf,CRLF);
    strcat(send_buf,CRLF);
    ret_send=soc_send(socket_id, send_buf,strlen(send_buf)+1,0);
    if(ret_send > 0)
    {

        my_socket_receive();
    }
    else if(ret_send != SOC_WOULDBLOCK)
    {
        soc_close(socket_id);    

        return ;
    }
}
/********************************send http request end*********************/
/********************************receive http response start*****************/
Void my_socket_receive()
{
    Kal_int32 ret_recv=0;
    recv_buf = OslMalloc(1000);
    memset(recv_buf,0,sizeof(recv_buf));
    ret_recv = soc_recv(socket_id,recv_buf,sizeof(recv_buf),0);
    if(ret_recv > 0)
    {
        kal_prompt_trace(MOD_MMI,”my socket receive success,%s”,recv_buf);
    }
    else if(ret_recv != SOC_WOULDBLOCK)
    {
        soc_close(socket_id);    

        return ;
    }
}
/**********************************receive http response end*********************/
/****************app socket notify indication handler start*************************/
MMI_BOOL my_socket_notify (void* msg_ptr)
{
    app_soc_notify_ind_struct* my_soc_notify = (app_soc_notify_ind_struct*)msg_ptr;
    kal_int8 ret_connect=SOC_ERROR;
    if(my_soc_notify->socket_id != socket_id)
    {
        return MMI_FALSE;
    }
    switch(my_soc_notify->event_type)
    {
        case SOC_READ:
            my_socket_receive();
            break;
        case SOC_WRITE:
            my_socket_send();
            break;
        case SOC_CONNECT:
            if(my_soc_notify->result == KAL_FALSE)
            {
                ret_connect = soc_connect(socket_id,&g_test_ip);    //与服务器建立连接
                if(ret_connect == SOC_SUCCESS)
                {
                    my_socket_send();                        //连接成功送http request
                }
                else if(ret_connect != SOC_WOULDBLOCK)            //连接失败
                {
                    soc_close(socket_id);        
                }
            }
            else if(my_soc_notify->result == KAL_TRUE)
            {
                my_socket_send();
            }
            break;
        case SOC_CLOSE:
            soc_close(socket_id);
            break;
    }
    return MMI_TRUE;
}
/******************app socket notify indication handler end*************************/
/***************app socket gethostbyname indication handler start*******************/
MMI_BOOL my_socket_get_host_by_name(void *msg_ptr)
{
    app_soc_get_host_by_name_ind_struct* dns_ind;
    kal_int8 ret_connect;
    kal_uint8 domain_app_id;    
    If(!(msg_ptr))
    {
        return MMI_FALSE;
    }
    dns_ind = (app_soc_get_host_by_name_ind_struct*)msg_ptr;
    domain_app_id = cbm_get_app_id(dns_ind->account_id);
    if(domain_app_id != app_id)
    {
        return MMI_FALSE;
    }
    If(dns_ind->result == KAL_TRUE)
    {
        memcpy(g_test_ip.addr,dns_ind->addr,dns_ind->addr_len);
        g_test_ip.addr_len = dns_ind->addr_len;
        g_test_ip.port = 80;
        g_test_ip.sock_type = SOC_SOCK_STREAM;
        ret_connect = soc_connect(socket_id,& g_test_ip);
        if(ret_connect == SOC_SUCCESS)
        {
            my_socket_send();
        }
        else if(ret_connect != SOC_WOULDBLOCK)
        {
            soc_close(socket_id);
        }
    }
    else if(dns_ind->result == KAL_FALSE)
    {
        soc_close(socket_id);
    }
    return MMI_TRUE;
}
/***************app socket gethostbyname indication handler end*******************/

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论