MTK 网络通信详解

首先声明,小弟不才,能力有限,在这里献丑了。有不足之处还望各位大牛多多指教。

先这里说一下 MTK 的通信流程,一些新人还是对这个不熟悉的。

其实这个和 PC 机的通信差不多,大同小异。 PC 机上是直接 send 发送数据的,而 MTK 是发送数据时要加一个 HTTP 头再发送出去,这就是传说中的 CMWAP 模式通信,与 CMWAP 并列的是 CMNET 通信,这里先不详讲 CMWAM 与 CMNET 了,后面弄个专题。

这张流程图,CSDN不知道怎么回事不能上传

呆会给个URL

下面来详细介绍下这些函数及注意事项

kal_int8 soc_create(kal_uint8  domain,

                    socket_type_enum  type,

                    kal_uint8  protocol,

                    module_type mod_id,

                    kal_uint32 nwk_account_id);
       比如

1)

kal_uint32 nwk_account_id = 10;

soc_create(PF_INET, SOCK_STREAM, 0, MOD_MMI, nwt_acount_id);

这里关键是 nwt_acount_id 这个值,很多 MTKer 都不知道这个值该填什么,一般情况下填 10 ,因为 10 在 MTK 手机里设置的 10 代表着中国移动,如果是 CMNET 通信的话就就填 14 了,如今的 MTK 手机都已经很牛 X 了,支持双卡双待。这时又得说明当前是通信是想有卡 1 还是卡 2 去通信,因为不同的卡 nwt_acount_id 又不一样,所以在 soc_create 之前得区分当前卡是卡 1 还是卡 2 。

2) kal_int8 soc_setsockopt(kal_int8 s,

                        kal_uint32 option,

                        void *val,

                        kal_uint8 val_size);

3)

U32 val1 = SOC_READ | SOC_WRITE | SOC_CLOSE | SOC_CONNECT;

soc_setsockopt(socketid, SOC_ASYNC, &val1, sizeof(val));

把 socketid 的设置成异步,选项有 SOC_READ , SOC_WRITE , SOC_CLOSE , SOC_CONNECT 。

 

       4)

       U32 val = 1;

soc_setsockopt(socketid, SOC_NBIO, &val, sizeof(val));

把 socketid 设置成非阻塞

 

       5)setProtocolEventHandler(soc_app_socket_notify, MSG_ID_APP_SOC_NOTIFY_IND);

设置消息的触发消息响应函数,当有 val1 的类型的触发消息时会自动调用 soc_app_socket_notify 这个函数。

       6) kal_int8 soc_connect(kal_int8 s, sockaddr_struct *addr);

       typedef struct

{

    socket_type_enum  sock_type;

    kal_int16 addr_len;

    kal_uint16      port;

    /* For keep the 4-byte boundary */

    /* please do not declare other variables above addr */

    kal_uint8 addr[MAX_SOCK_ADDR_LEN];

} sockaddr_struct;

CMWAP 通信时 , 手机端需要首先连接移动网关才能进行网络通信 , 这里需要填充结构体 sockaddr_struct 的 addr 及 port 成员 ,

 

sockaddr_struct sockaddr = {0};

sockaddr.addr[0] = 10;

sockaddr.addr[0] = 0;

sockaddr.addr[0] = 0;

sockaddr.addr[0] = 172;

sockaddr.addr_len = 4

sockaddr.port = 80;

 

如果是 CMNET 通信时就 IP 及端口填自己要访问的服务器 IP{byte1, byte2, byte3, byte4} 及地址 server_port

 

sockaddr_struct sockaddr = {0};

sockaddr.addr[0] = byte1;

sockaddr.addr[1] = byte2;

sockaddr.addr[2] = byte3;

sockaddr.addr[3] = byte4;

sockaddr.addr_len = 4

sockaddr.port = server_port;

 

 

到这里连接请求已经发送出去了。接着会有服务器发一个连接响应,也就是通知我服务器已经接到你客户端的连接请求,这里在客户端也就会触发我们先前设置的 SOC_CONNECT 消息 ,并由 soc_app_socket_notify 来响应这个事件 .

这是原型 void soc_app_socket_notify(void *inMsg);

而 inMsg 指向的是 app_soc_notify_ind_struct 这么一个结构体

typedef struct

{

   kal_uint8       ref_count;

   kal_uint16      msg_len;     

   kal_int8        socket_id;    /* socket ID */

   soc_event_enum  event_type;   /* soc_event_enum */

   kal_bool        result;

   soc_error_enum  error_cause;  /* used only when EVENT is close/connect */

   kal_int32       detail_cause; /* refer to ps_cause_enum if error_cause is

                                  * SOC_BEARER_FAIL */

} app_soc_notify_ind_struct;

 

/* event */

typedef enum

{

    SOC_READ    = 0x01,  /* Notify for read */

    SOC_WRITE   = 0x02,  /* Notify for write */

    SOC_ACCEPT  = 0x04,  /* Notify for accept */

    SOC_CONNECT = 0x08,  /* Notify for connect */

    SOC_CLOSE   = 0x10   /* Notify for close */

} soc_event_enum;

 

/* Socket return codes, negative values stand for errors */

typedef enum

{

    SOC_SUCCESS           = 0,

    SOC_ERROR             = -1,

    SOC_WOULDBLOCK        = -2,

    SOC_LIMIT_RESOURCE    = -3,    /* limited resource */

    SOC_INVALID_SOCKET    = -4,    /* invalid socket */

    SOC_INVALID_ACCOUNT   = -5,    /* invalid account id */

    SOC_NAMETOOLONG       = -6,    /* address too long */

    SOC_ALREADY           = -7,    /* operation already in progress */

    SOC_OPNOTSUPP         = -8,    /* operation not support */

    SOC_CONNABORTED       = -9,    /* Software caused connection abort */

    SOC_INVAL             = -10,   /* invalid argument */

    SOC_PIPE              = -11,    /* broken pipe */

    SOC_NOTCONN           = -12,   /* socket is not connected */

    SOC_MSGSIZE           = -13,   /* msg is too long */

    SOC_BEARER_FAIL       = -14,   /* bearer is broken */

    SOC_CONNRESET         = -15,   /* TCP half-write close, i.e., FINED */

    SOC_DHCP_ERROR        = -16,

    SOC_IP_CHANGED        = -17,

    SOC_ADDRINUSE         = -18,

    SOC_CANCEL_ACT_BEARER = -19    /* cancel the activation of bearer */

} soc_error_enum;

 

在这里 app_soc_notify_ind_struct 里会经常捕捉到错误的 SOC_CONNECT 消息,这时 app_soc_notify_ind_struct 里的 result 为 KAL_FALSE, soc_error_enum 为 -14 ( SOC_BEARER_FAIL ),表示建立连接失败。分析了原因,有以下几个原因,一、 soc_create 时的 nwk_conunt_id 弄错了,二、 soc_connect 的 IP 和端口弄错了,三、手机卡,没话费了,四、手机卡没有开通 GPRS 。

 

 

 

       7) 发送数据

       仅有当 SOC_CONNECT 消息正常触发,且拥有正确的值时就可以直接 soc_send 了

  kal_int32 soc_send(kal_int8 s,

                   kal_uint8 *buf,

                   kal_int32 len,

                   kal_uint8 flags)

eg

S32 ret = 0;

char buf[1024*20] = {0};

http_get_buf(buf);

ret = soc_send(socketid, buf, strlen(buf), 0);

 

8) 如果发送成功的话,这里有一个 SOC_RECV 三番五次来造访我们的 soc_app_socket_notify 函数,我们也别客气。开始接收数据

kal_int32 soc_recv(kal_int8 s,

                   kal_uint8 *buf,

                   kal_int32 len,

                   kal_uint8 flags)

eg

S32 ret = 0;

char buf[1024*20] = {0};

ret = soc_recv(socketid, buf, 1024*20, 0);

 

9) 最后接收完了就可以关闭 socket 了

       soc_close(socketid);

你可能感兴趣的:(职场,MTK,休闲,soc_socket)