展讯6531平台socket

来源:互联网 发布:淘宝月销量怎么变少了 编辑:程序博客网 时间:2024/06/07 04:50

最近公司接到一个新项目,搞展讯6531E平台的天气预报,基本流程其实也简单,就是手机端发送一个请求到服务器,然后服务器把数据发送回来,手机端接收并且解析就可以了,由于之前没有做过展讯socket相关的东西,网上能搜索到的资源非常有限,所以在此做个总结,非常欢迎展友给我指出其中的错误以及纰漏。

功能基本流程如下:

1、激活PDP、拿到net_id

2、socket 通信

3、关闭socket

4、detach PDP


说明:这个流程有很大的局限性,因为手机端跟服务器端只有请求跟相应请求两个交互,再无其他交互,所以设计的很简单,但是socket的操作六层大致如此


1、激活PDP

//TEST cmnet 回调函数
LOCAL void HandlePDPTESTMsg(MMIPDP_CNF_INFO_T *msg_ptr)
{
        if(PNULL == msg_ptr)
           {
                return;
        }
        SCI_TRACE_LOW("[MMIMMS]:HandlePDPTESTMsg msg_id=%d",msg_ptr->msg_id);
        switch(msg_ptr->msg_id)
        {
        case MMIPDP_ACTIVE_CNF:
            if(msg_ptr->result != 0)
            {
                //记得把else里面重复激活PDP的定时器关闭
                taiodu_net_id = msg_ptr->nsapi;   //这个是net_id 知名socket使用的链路
                SCI_TRACE_LOW("+++++++HandlePDPTESTMsg,case MMIPDP_ACTIVE_CNF,taiodu_net_id :%ld",taiodu_net_id);        
                TEST_OpenSocket();   //建立sock,开始搞事
            }else
            {
                //这里再开一个定时器,继续调用openTESTNet,一直到这个回调接收到MMIPDP_ACTIVE_CNF,并且msg_ptr->result != 0
            }
            break;
            // MMK_PostMsg(MAIN_IDLE_WIN_ID, MSG_TEST_NETLINK_SUCCESS, PNULL,0); //发送网络激活成功 break;
        case MMIPDP_DEACTIVE_CNF:
                break;
        case MMIPDP_DEACTIVE_IND:
                SCI_TRACE_LOW("+++++++HandlePDPMsg: MMIPDP_DEACTIVE_IND");
                //MMK_PostMsg(MAIN_IDLE_WIN_ID, MSG_TEST_NETLINK_DISCONNECT, PNULL,0); //发送网络断开 break;
        default:
                break;
        }
        //SCI_FREE(msg_ptr);
}


//打开cmnet
BOOLEAN openTESTNet(void)
{
        MMIPDP_ACTIVE_INFO_T active_info = {0};
        char apn_ptr[10] = {0};//apn string
        BOOLEAN ret = FALSE;
        strcpy(apn_ptr,"cmnet");
        if (MMIPHONE_IsSimAvailable(0))//判断飞行模式
        {
                SCI_TRACE_LOW("openTESTNet");

                active_info.dual_sys = 0;

                //注意这个auth_type,6531E的代码需要更新过新的网络参数工具

                active_info.auth_type = 1;
                active_info.priority = 3;
                active_info.app_handler = MMI_MODULE_COMMON;
                active_info.handle_msg_callback = HandlePDPTESTMsg;
                active_info.apn_ptr = apn_ptr;
                active_info.ps_service_rat = MN_TD_PREFER;        
                MNGPRS_ReadStorageExtReqQosEx(active_info.dual_sys,MN_GPRS_STORAGE_ALL,BROWSER_E,&active_info.qos_info);                
                ret =MMIAPIPDP_Active(&active_info);
        }
        SCI_TRACE_LOW("openTESTNet :MMIAPIPDP_Active = %d!", ret);
        return ret;
}


2、socket通信

Socket int TEST_OpenSocket(void)
{
        struct sci_sockaddr server_addr; unsigned short  port = TEST_URL_PORT;           /* port number */
        int taiduSockfd = -1;
        int ret = 0; //初始化socket
        int err = 0;
        BLOCK_ID task_id = 获取当前线程的ID,接口我忘记了,找到了再更新
        XsignalHheaderRec *sig_ptr = NULL;
        char *sen_buf = "test send data";
        char recv_data[1024] = {0};
        BOOLEAN is_break = FALSE;
        if((taiduSockfd = sci_sock_socket(AF_INET,SOCK_STREAM,0,taiodu_net_id)) == -1)
        {
            return -1;
        }
        SCI_TRACE_LOW("TEST_OpenSocket:Socket = %d\n", taiduSockfd);
        //设置socket属性,非阻塞模式
        //这里要注意,非阻塞模式下,通信接口都是立马返回的,所以单靠返回值判断状态是不可靠的,我就在这个坑里面挣扎了好久。。。
        sci_sock_setsockopt(taiduSockfd,SO_NBIO, NULL);
        
        server_addr.family = AF_INET;
        server_addr.port = htons(port);
        server_addr.ip_addr = inet_addr(TEST_URL_ADDRESS);
        SCI_TRACE_LOW("TEST_OpenSocket:begin sci_sock_connect!! \n");                
        SCI_TRACE_LOW("TEST_OpenSocket:server_addr.port=%d!! \n",server_addr.port);
        SCI_TRACE_LOW("TEST_OpenSocket:server_addr.ip_addr=%d!! \n",server_addr.ip_addr);
        SCI_TRACE_LOW("TEST_OpenSocket:sizeof(server_addr)=%d!! \n",sizeof(server_addr));
        ret = sci_sock_connect(taiduSockfd,&server_addr,sizeof(server_addr)) ;
        if(ret == -1)
        {
            while(1)//一直发起连接,非阻塞模式下,重复调用连接同一端口的,会返回
            {
                err = sci_sock_errno(taiduSockfd);   //得到错误码
                if(EINPROGRESS != err)   //表明其他严重的错误,需要关闭socket
                {
                    sci_sock_socketclose(taiduSockfd);
                    return -1;
                }
                ret = sci_sock_connect(taiduSockfd);
                if(ret == 0)  //终于连接成功了,那就结束重复连接吧
                {
                    break;
                }
            }
            //表明正在连接,等到服务端的相应
        }
        
        //接下来需要监听socket的一下动态,所以需要设置你感兴趣的消息,来捕捉动态
        //这里我需要检测,连接,关闭,读,写的状态事件
        sci_sock_asyncselect(taiduSockfd, task_id, AS_CONNWCT|AS_READ|AS_WRITE|AS_CLOSE);
        
        //先发送请求
        sci_sock_sen(taiduSockfd, sen_buf, sizeof(sen_buf), 0);
        //注意,这里可能发送缓存已经满了,发送失败,没关系,失败了可以再task里捕捉write消息,这个时候可以继续发送请求
        
        //接下来在这里收发数据了
        
        
        is_break = TRUE;
        while(is_break)
        {
            //从这个task里获取到消息,然后这里处理
            sig_ptr = SCI_GetSignal(task_id);
            
            switch(sig_ptr->SignalCode)
            {
                case SOCKET_CONNECT_EVENT_IND:
                //连接了,其实这条消息已经过时了,前面sci_sock_connect的时候已经产生了,所以我在while(1)外边就发送请求了,因为已经连接了
                    break:
                case SOCKET_CONNECT_CLOSE_EVENT_IND:
                    is_break = FALSE; //结束了
                    break;
                case SOCKET_READ_EVENT_IND:
                    //这里可以接收数据了
                    sci_sock_recv(taiduSockfd, recv_data, sizeof(recv_data), 0);
                    break;
                case SOCKET_WRITE_EVENT_IND:
                    //应该是前面发送请求失败了
                    sci_sock_sen(taiduSockfd, sen_buf, sizeof(sen_buf), 0);
                    break;
            }
        }
        
        
        SCI_TRACE_LOW("TEST_OpenSocket:ret , %d\n", ret );
        SCI_TRACE_LOW("TEST_OpenSocket:ret=%d!! \n",ret);
        
        sci_sock_socketclose(taiduSockfd);
        return taiduSockfd;
}

原创粉丝点击