C 语言-基于 P1300 的 SOCKET 实现

(罗锋 luof520@163.com)

一.怎样使用手机工程模式下 socket

例子
第一步:开通 GPRS 业务
手机拨打 1860 或者发送短信开通 GPRS 套餐。包月 5 元 ,包含 CMWAP 流量 30M/月,如果产生 CMNET 流量,按照 1 元/M 收取。
第二步:设置账号
工程模式下, AccountId 使用 custom_get_csd_profile_num()=10(“网络服务\账号资料\GSM”下条目总数),10 的值对应 “网络服务\账号资料\GPRS\”下的“FFT GPRS” 账号信息,但是实际使用中国移动 GPRS CMNET 对应 AccountId=17,所以需要修改此账号。
修改方法:编辑 “FFT GPRS 菜单下的“GPRS 连结点”,由“fetnet01”修改为“CMNET”.
也可修改代码读取“网络服务\账号资料\”里面的设置值。
第三步:进入工程模式
在手机待机界面,点击拨号盘,输入“*#3646633#”,即进入工程模式.
第四步:进行 SOCKET 实验
“Socket Test” 菜单下共有六个选项,使用说明如下:
DNS QUERY----域名解析,输入网址,返回 IP.
举例:输入 www.google.com , 返回 Google 的 IP 地址 64.233.189.99
HTTP GET------输入网址,返回网页信息
举例: 输入 http://www.google.com ,返回
ECHO------------服务器端返回客户端发送的数据。 经过测试,输入后,返回错误,可能服务器端不支持
Date Query-------获取服务器日期时间数据 经过测试,输入后返回错误,可能服务器端不支持
TraceRt---------- 获取路由信息表
例如: 输入 www.google.com,返回数据经过的路由地址和时间
Iperf --------------程序没有实现

二.P1300 socket 编程介绍

1. CMWAP 与 CMNET

cmwap 和 cmnet 是中国移动 gprs 网络的两个不同的 APN(Access Point Name 接入点名称)。
cmnet 提供 NET 服务,手机使用该服务可以直接访问 internet,获得完全的 internet 访问权,与电脑接入互联网完全一样;
而 cmwap 只能访问 wap 网站,当然也可 以 http 代理协议(80 和 8080 端口)和 wap 网关协议(9201 端口)访问 internet.
总结:cmwap 通过代理路由访问 internet 网,cmnet 直接访问 internet 网!P1300 同时支持 cmwap 和 cmnet 的接入。

2. P1300 socket 接口函数
soc_create---------创建 socket 接口,
其第二个参数表示 Socket 类型,常用的 Socket 类型有两种: 流式 Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。
流式 Socket 是一种面向连接的 Socket,针对于面向连接的 TCP 服务应用; 数据报式 Socket 是一种无连接的 Socket,对应于无连接的 UDP 服务应用。
soc_setsockop----设置 socket option: 非阻塞模式 和 异步 IO 手机平台通讯都是非阻塞模式,因此 soc_connect 和 soc_recv 一般不会马上返 回成功,而是返回 SOC_WOULDBLOCK.意思是要等待一会儿,.所以我们要调用 SetProtocolEventHandler 来设置回调函数处理。
soc_connect---连接指定的 Server,如:代理服务器 10.0.0.172:80。只有面向连接(tcp) 的客户程序使用 socket 时才需要将此 socket 与远端主机相连。无连接协议 (udp)从不建立直接连接。
soc_send------用于面向连接(tcp)的socket方式下数据传输,发送客户端请求
soc_recv------用于面向连接(tcp)的socket方式下数据传输,接收服务器返
回信息 soc_sendto----用于无连接(udp)的数据报socket方式下数据传输, 发送客户端请求 soc_recvfrom-用于无连接(udp)的数据报socket方式下数据传输, 接收服务器返回信息 soc_close----关闭 socket 连接

三.TCP 和 UDP 通讯流程

socket 的 udp 方式通讯流程描述
<1>soc_create, 其第二个参数设置为 SOCK_DGRAM
<2>soc_sendto
<3>soc_revfrom
<4>soc_close

socket 的 tcp 方式通讯流程描述
<1>soc_create, 其第二个参数设置为 SOCK_STREAM
<2>soc_connect
<3>soc_send
<4>soc_rev
<5>soc_close

四.P1300 socket 编程实现

目的:通过 CMWAP 和 CMNET 采用 TCP 方式连接 www.google.com
进入程序:手机上输入*#123456#就会调用 SSCHandleMySocket。显示空白,按左键启动 程序,连接过程会有打印信息提示,按右键退出
程序说明:

1>使用 CMWAP 连接
static kal_uint32 account_id=14;
kal_uint8 addr[4] = {10, 0, 0, 172};

2>使用 CMNET 连接
static kal_uint32 account_id=17;
kal_uint8 addr[4] = {64, 233, 189, 99};

64, 233, 189, 99 是 www.googel.com 的 ip 地址
3>CMWAP 和 CMNET 采用 TCP 方式连接的区别在于,CMWAP 方式 comnnect 移动网关;CMWAP 方式直接 connect 目标地址
修改说明:
<1>plutommi\mmi\ssc\sscsrc\SSCStringHandle.h 添加#define SSC_MYSOCKET "*#123456#"
<2> \plutommi\mtkapp\EngineerMode\EngineerModeInc\EngineerModeDef.h typedef enum {}EM_SCR_IDS 中添加 EM_MAIN_MENU_SCR,
<3> plutommi\mmi\ssc\sscsrc\SSCStringHandle.c ssc_table1[]中添加{SSC_MYSOCKET"*#123321#",MMI_FALSE,SSCHandleMySocket}

#include "MainMenuDef.h"
#include "EngineerModeDef.h"
#include"soc_api.h"
#define SOCKET_PACKAGE_HEAD "GET http://www.google.cn HTTP/1.1\r\nHost:www.google.cn\r\nProxy-Connection: Keep-Alive\r\n\r\n"

static kal_int8 socket_id=-1;
//static kal_uint32 account_id=14;
// cmwap 方式连接 static kal_uint32 account_id=17;
// cmnet 方式连接 static sockaddr_struct socket_addr;
static char rec_tmp[50];
static int print_x=0;

void mmi_Mysocket_exit(void) ;
static void init_socket(void) ;
void socket_receive(void);
void socket_send(void);
void notify_socket(void *inMsg);
extern void soc_init_win32(void);

static void SSCHandleMySocket(void)
{
EntryNewScreen(EM_MY_SOCKET_SCR, mmi_Mysocket_exit, NULL, NULL);
entry_full_screen();
clear_screen();
gui_BLT_double_buffer(0, 0, UI_device_width - 1, UI_device_height - 1);
SetKeyHandler(GoBackHistory, KEY_RSK, KEY_EVENT_UP);
SetKeyHandler(init_socket, KEY_LSK, KEY_EVENT_UP);
}

static void print_reset()
{
print_x=0;
}

static void print_soc_info(UI_string_type info) //luofadd 09-07-21
{
gui_move_text_cursor(0,print_x);
gui_set_text_color(UI_COLOR_RED);
gui_print_text((UI_string_type)info);
gui_BLT_double_buffer(0,0,UI_device_width-1,UI_device_height-1);
print_x+=30;
}

void socket_receive(void)
{
kal_int32 result;
U16 tmp2[50]; //接收的字节数自行调节
memset((void*)rec_tmp,0,50);
result=soc_recv(socket_id,(kal_uint8*)rec_tmp,50,0);
if(result>0)
{
char i;
print_soc_info(L"--rev OK!");
for(i=0;i<result;i++)
tmp2[i]=0x00ff&((U16)rec_tmp[i]);
print_soc_info(tmp2);
return;
}
else if(result==0)
{
print_soc_info(L"--rev result==0!");
SetProtocolEventHandler(notify_socket, MSG_ID_APP_SOC_NOTIFY_IND);
return;
}
else if(result==SOC_WOULDBLOCK)
{
}
else
{
print_soc_info(L"--rev SOC_WOULDBLOCK!");
SetProtocolEventHandler(notify_socket, SG_ID_APP_SOC_NOTIFY_IND);
return;
}

print_soc_info(L"--rev error!");
soc_close(socket_id);
return;
}

void socket_send(void)
{
kal_int32 result;
result=soc_send(socket_id,(kal_uint8*)SOCKET_PACKAGE_HEAD,strlen(SOCKET_PACK AGE_HEAD),0);
if(result>0)
{
print_soc_info(L"--send OK!");
socket_receive();
return;
}
else
{
if(result==SOC_WOULDBLOCK)
{
print_soc_info(L"--send SOC_WOULDBLOCK!");
SetProtocolEventHandler(notify_socket, MSG_ID_APP_SOC_NOTIFY_IND);
return;
}
else
{
if(result==SOC_ERROR)
{
print_soc_info(L"--send error!");
soc_close(socket_id);
return;
}
else
{
print_soc_info(L"--send other error!");
soc_close(socket_id);
return;
}
}
}
}
void notify_socket(void *inMsg)
{
app_soc_notify_ind_struct *soc_notify;
soc_notify=(app_soc_notify_ind_struct *)inMsg;
print_soc_info(L"Notify Soket!");
if(soc_notify->socket_id!=socket_id)
{
else
print_soc_info(L"---Notify NO Socket!");
return;
}

switch(soc_notify->event_type)
{
case SOC_WRITE:
print_soc_info(L"---Notify Socket Write!");
break;
case SOC_READ:
print_soc_info(L"---Notify Socket Read!");
socket_receive();
break;
case SOC_CONNECT:
print_soc_info(L"--Notify Soket Connect!");
socket_send();
break;
case SOC_CLOSE:
print_soc_info(L"---Notify Soket Close!");
soc_close(socket_id);
break;
default:
print_soc_info(L"---Noticfy Scket Error!");
soc_close(socket_id);
socket_id=-1;
break;
}
}
static void init_socket(void)
{
kal_int8 ret;
kal_uint8 val=1;
#ifndef MMI_ON_HARDWARE_P
kal_uint8 addr[4] = {192, 168, 0, 1};
#else
//kal_uint8 addr[4] = {10, 0, 0, 172}; //cmwap 方式连接
kal_uint8 addr[4] = {64, 233, 189, 99};//www.googel.com cmnet 方式连接
#endif print_reset();
#ifndef MMI_ON_HARDWARE_P
soc_init_win32(); //PC 仿真使用
#endif
print_soc_info(L"Start Soket Create!");
socket_id=soc_create(PF_INET,SOCK_STREAM,0,MOD_MMI,account_id);//新建连接
if(socket_id<0)
{
print_soc_info(L"Socket Create Error!");
return;
}
else
{
if(soc_setsockopt(socket_id,SOC_NBIO,&val,sizeof(val))<0)//设置 socket 非阻塞模式
{
print_soc_info(L"Set socket to nonblock mode error!");
return;
}
val=SOC_READ|SOC_WRITE|SOC_CLOSE|SOC_CONNECT;
if(soc_setsockopt(socket_id,SOC_ASYNC,&val,sizeof(val))<0)//设置异步 I/O
{
print_soc_info(L"Set socket to nonblock mode error!");
return;
}
}
print_soc_info(L"Start Socket Created Connect!");
socket_addr.addr_len=4;
#ifndef MMI_ON_HARDWARE_P
socket_addr.addr[0]=192;
socket_addr.addr[1]=168;
socket_addr.addr[2]=1;
socket_addr.addr[3]=1;
socket_addr.port=80;
#else memcpy(socket_addr.addr,addr, 4);
#endif
socket_addr.port=80;
ret=soc_connect(socket_id,&socket_addr);
if(ret==SOC_SUCCESS)
{
    print_soc_info(L"connect SOC_SUCCESS!");
    socket_send();
}
else if(ret==SOC_WOULDBLOCK)
{
    print_soc_info(L"connect SOC_WOULDBLOCK!");
    SetProtocolEventHandler(notify_socket, MSG_ID_APP_SOC_NOTIFY_IND);
    return;
}
else
{
    if(ret==SOC_ERROR)
    {
        print_soc_info(L"connect SOC_ERROR!!");
        soc_close(socket_id);
        return;
    }
print_soc_info(L"connect OTHER_ERROR!!");
soc_close(socket_id);
return;
}
}
static void exit_socket()
{
    soc_close(socket_id);
    print_soc_info(L"Start Socket Close!");
}
void mmi_Mysocket_exit(void)
{
    history currHistory;
    S16 nHistory = 0;
    currHistory.scrnID = MAIN_MENU_SCREENID;
    currHistory.entryFuncPtr = SSCHandleMySocket;
    pfnUnicodeStrcpy( (S8*)currHistory.inputBuffer, (S8*)&nHistory); AddHistory(currHistory);
    exit_socket();
}

查看本机 ip 开始/运行 输入 CMD, 进入 dos 界面,输入 ipconfig, 显示如下界面,红色为本机 IP,蓝色为网关 IP.
302 Found

302 Found


nginx/1.8.0