首先声明,小弟不才,能力有限,在这里献丑了。有不足之处还望各位大牛多多指教。 先这里说一下 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 网络通信详解
精选 转载曾永刚 博主文章分类:Embeded Linux
![](https://ucenter.51cto.com/images/noavatar_middle.gif)
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章