最近公司接到一个新项目,搞展讯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时间
PUBLIC uint32 HxWeather_CreateTask(void)
{
if (0 != s_weather_task_id)
{
//之前创建的task还没有关闭!
return 0;
}
s_weather_task_id = SCI_CreateThread(
"T_WEATHER",
"Q_WEATHER",
Weather_TaskHandle,
0,
0,
WEATHER_STACK_SIZE,
WEATHER_STACK_QUEUE_NUM,
#ifdef WIN32
30,
#else
PRI_APP_WEATHER_TASK,
#endif
SCI_PREEMPT,
SCI_AUTO_START);
SCI_TRACE_LOW(" HxWeather_CreateTask create task ID %d", s_weather_task_id);
return s_weather_task_id;
}
LOCAL void Weather_TaskHandle(uint32 argc, void * argv)
{
xSignalHeaderRec *signal_ptr = PNULL;
uint32 sock_id = 0;
static BOOLEAN is_on_free= FALSE;
BLOCK_ID tsak_id = SCI_IdentifyThread(); // 获取当前taskID
for(;;)
{
SCI_TRACE_LOW("Weather_TaskHandle Entry for(;;) !");
signal_ptr = (xSignalHeaderRec *)SCI_GetSignal(tsak_id);
SCI_TRACE_LOW("Weather_TaskHandle sci_sock_select sig_ptr->SignalCode = %d",signal_ptr->SignalCode);
SCI_TRACE_LOW("Weather_TaskHandle sci_sock_select sig_ptr->SignalCode = %d",signal_ptr->SignalCode);
SCI_TRACE_LOW("Weather_TaskHandle sci_sock_select sig_ptr->SignalCode = %d",signal_ptr->SignalCode);
SCI_TRACE_LOW("Weather_TaskHandle sci_sock_select sig_ptr->SignalCode = %d",signal_ptr->SignalCode);
if (PNULL != signal_ptr)
{
switch(signal_ptr->SignalCode)
{
case SOCKET_READ_EVENT_IND: //
//可读
if(HxWeatherRecvData(s_cosket_id))
{
//解析数据
//is_continue = FALSE;
//SCI_ThreadExit();
}else
{
//接收错误会返回到这里
HxWeatherUpdateSetErrorType(HX_WEATHER_UPDATE_ERROR_RECV_DATA);
//is_continue = FALSE;
//SCI_ThreadExit();
}
break;
case SOCKET_CONNECTION_CLOSE_EVENT_IND:
//is_continue = FALSE; //结束循环
SCI_TRACE_LOW("Weather_TaskHandle exit sur thread task!");
s_weather_task_id = 0;
SCI_ThreadExit();
//关闭
break;
case SOCKET_WRITE_EVENT_IND:
memset(G_Weather_Dta, 0, G_Data_Buffer);
SCI_TRACE_LOW("Weather_TaskHandle memset G_Weather_Dta 0 !");
HxWeatherSendRequest(s_cosket_id);
//连接
break;
default :
break;
}
}else
{
SCI_TRACE_LOW("Weather_TaskHandle SCI_GetSignal ptr is NULL!");
}
#if 0
if (!s_weather_task_id)
{
SCI_TRACE_LOW("Weather_TaskHandle exit sur thread task for ");
SCI_ThreadExit();
}
#endif
}
}
打开socket
LOCAL int HxWeather_OpenSocket(void)
{
int32 socket_id = 0;
int return_ret = 0;
int error = 0;
struct sci_sockaddr addr;
//struct sci_sockaddrext connect_add;
struct sci_hostent * hostent_date = PNULL;
uint32 ip = 0;
uint32 hostip = 0;
int rept_connect = 0;
//int32 host_ip = 0;
char addr_buf[128] = {0};
uint16 port = 10620;
sci_fd_set writefds;
BLOCK_ID tsak_id = s_weather_task_id;//为socket事件新建的线程,由他来检测socket的动态,如果使用主线程,会导致主线程阻塞,系统崩溃
BOOLEAN is_continue = FALSE;
xSignalHeaderRec* sig_ptr = NULL; //task signal
//创建socket
socket_id = sci_sock_socket(AF_INET, SOCK_STREAM, 0, s_weather_net_id);
s_cosket_id = socket_id;
SCI_TRACE_LOW("HxWeather_OpenSocket socket_id = %d",socket_id);
SCI_TRACE_LOW("HxWeather_OpenSocket socket_id = %d",socket_id);
SCI_TRACE_LOW("HxWeather_OpenSocket s_weather_net_id = %d",s_weather_net_id);
SCI_TRACE_LOW("HxWeather_OpenSocket s_weather_net_id = %d",s_weather_net_id);
if(socket_id == TCPIP_SOCKET_INVALID)
{
HxWeatherUpdateSetErrorType(HX_WEATHER_UPDATE_ERROR_SOCKET_CREATE);
return 0;
}
//设置属性
error = sci_sock_setsockopt(socket_id, SO_NBIO, PNULL);//设置socket 为非阻塞模式
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_setsockopt error = %d",error);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_setsockopt error = %d",error);
if(-1 == error )//失败
{
error = sci_sock_errno(socket_id);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_errno error = %x",error);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_errno error = %x",error);
HxWeatherUpdateSetErrorType(HX_WEATHER_UPDATE_ERROR_SOCKET_CREATE);
sci_sock_socketclose(socket_id);
return 0;
}
#if 0
error = sci_sock_setsockopt(socket_id, SS_ASYNC, NULL);
if(-1 == return_ret)
{
error = sci_sock_errno(socket_id);
sci_sock_socketclose(socket_id);
return 0;
}
#endif
//绑定
//return_ret = sci_parse_host((char *)g_hxweather_domain,&ip,0);
// return_ret = sci_parse_host_ext((char *)g_hxweather_domain, &ip, 0, s_weather_net_id);
hostent_date = sci_gethostbyname(g_hxweather_domain);
//SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext ip = %x",ip);
//SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext ip = %x",ip);
//SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext return_ret = %d",return_ret);
//SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext return_ret = %d",return_ret);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext hostent_date = %x",hostent_date);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext hostent_date = %x",hostent_date);
//SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext IP = %s",*(hostent_date->h_addr_list));
//SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext IP = %s",*(hostent_date->h_addr_list));
if(NULL == hostent_date) //获取IP addr失败
{
HxWeatherUpdateSetErrorType(HX_WEATHER_UPDATE_ERROR_GET_HOSTNAME);
sci_sock_socketclose(socket_id);
return 0;
}
SCI_MEMCPY(&hostip, hostent_date->h_addr_list[0], 4);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext hostip = %d",hostip);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext hostip = %d",hostip);
//ntohl(ip);
ip = ntohl(hostip);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext ip = %x",ip);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext ip = %x",ip);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext return_ret = %d",return_ret);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext return_ret = %d",return_ret);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext hostent_date->h_addr_list = %s",hostent_date->h_addr_list[0]);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext hostent_date->h_addr_list = %s",hostent_date->h_addr_list[0]);
addr.family = AF_INET;
//addr.ip_addr = htonl(ip);
addr.ip_addr = htonl(ip);
addr.port = htons(port);
//memset(addr.sa_data, 0, 8 * sizeof(char));
SCI_MEMSET((void*)addr.sa_data, 0, 8*sizeof(char));
//sci_sock_bind(socket_id, &addr, sizeof(struct sci_sockaddr));
//连接
//非阻塞方式需要等待连接成功
return_ret = sci_sock_connect(socket_id, &addr, sizeof(struct sci_sockaddr));
if(-1 == return_ret)
{
for(rept_connect = 0; rept_connect < HXWEATHER_REPT_CONNECT_NUMBER; rept_connect ++)
{
//取得错误的原因
error = sci_sock_errno(socket_id);
if(error != EINPROGRESS) //不是这个错误号的都需要关闭socket,属于严重的错误
{
HxWeatherUpdateSetErrorType(HX_WEATHER_UPDATE_ERROR_SOCK_CONNECT);
sci_sock_socketclose(socket_id);
return 0;
}
SCI_SLEEP(HXWEATHER_REPT_CONNECT_TIME); // 1S一次重连
return_ret = sci_sock_connect(socket_id, &addr, sizeof(struct sci_sockaddr));
if(0 == return_ret) // 重连成功,跳出循环
{
break;
}
}
//获取错误的原因
//error = sci_sock_errno(socket_id);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_connect eror_num = %d",error);
}
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_connect return_ret = %d",return_ret);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_connect return_ret = %d",return_ret);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext addr.ip_addr = %x",addr.ip_addr);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_parse_host_ext addr.ip_addr = %x",addr.ip_addr);
//监听
//socket = s_mr_sockets[param].s;
SCI_FD_ZERO (&writefds);
SCI_FD_SET((long)socket_id, &writefds);
//sci_sock_select(sci_fd_set * in, sci_fd_set * out, sci_fd_set * ex, long tv)
return_ret = sci_sock_select(NULL, &writefds, NULL, 0);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_select return_ret = %d",return_ret);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_select return_ret = %d",return_ret);
//注册event消息
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_asyncselect task ID:%d", s_weather_task_id);
return_ret = sci_sock_asyncselect(socket_id, s_weather_task_id, AS_CONNECT|AS_READ|AS_WRITE|AS_CLOSE);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_select sci_sock_asyncselect = %d",return_ret);
SCI_TRACE_LOW("HxWeather_OpenSocket sci_sock_select sci_sock_asyncselect = %d",return_ret);
if(return_ret == -1)
{
sci_sock_errno(socket_id);
}
is_continue = TRUE;
//前面connect连接成功,表明可以发送数据了....
HxWeatherSendRequest(socket_id); //有可能发送过程中,buf不足,发送失败,在下面的task里等待WRITE消息,继续发送
//MMIAPIPDP_Deactive(MMI_MODULE_HXWEATHER);
//sci_sock_connect(TCPIP_SOCKET_T so, struct sci_sockaddrext * addr_ptr, int addr_len)
return socket_id;
}