您的位置:首页 > 理论基础 > 计算机网络

SOCKET_MTK网络通信流程图

2016-01-28 16:00 567 查看
其实这个和 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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: