AT_TCPIP_CmdFunc_CIPSTART
//start up tcpip connection
1)if (gCipBearer != BEARER_WIFI)
承载是GPRS(1)还是WIFI(2),若非WIFI,获取SimStatus
2)if ((!cipMux_multiIp && (CIP_INITIALg_uCipContexts.nBearerParas[BEARER_GPRS_DEF].nState ||
CIP_STATUS_uCipContexts.nBearerParas[BEARER_GPRS_DEF].nState)) || (cipMux_multiIp && (CIP_STATUS = = bearerParas->nState || CIP_GPRSACT == bearerParas->nState)))
//只有在(单IP模式 且 (状态等于0【初始化】或者5【已获取IP】))或者
(多IP模式 且 (状态等于5【已获取IP】或者7【已激活状态】))
状态下才可以进行连接的建立,连接建立成功后的状态为CONNECT OK,连接失败,则处于失败的状态下。
if ((!cipMux_multiIp && pParam->paramCount != 3) || (cipMux_multiIp && pParam->paramCount != 4))
//判断参数个数
uMuxIndex = at_ParamUintInRange(pParam->params[0], 0, 7, ¶mok);
//复用的连接号(0-7)
const uint8_t *mode = at_ParamStrOrText(pParam->params[0 + cipMux_multiIp], ¶mok); //类型(TCP/UDP)
const uint8_t *ipaddress = at_ParamStr(pParam->params[1 + cipMux_multiIp], ¶mok);//IP地址
uPort = at_ParamUintInRange(pParam->params[2 + cipMux_multiIp], 0, 65535, ¶mok);//端口号
if ((CIP_INITIAL = = bearerParas->nState || gOutsidePdpCid == 1) && !useOutsidePdp(pParam->nDLCI,1)) //如果已有连接存在且已初始化,则获取ID,设置APN,激活 ??
否则进行AT_TCPIP_Connect:
进行域名解析,成功返回RESOLV_COMPLETE:
CFW_TcpipSocketEX(tcpipParas->uDomain,tcpipParas->uType,tcpipParas->uProtocol,tcpip_rsp, nMuxIndex << 16 | nDLCI); //TcpipSocketEX
实际调用 lwip_socket(新建了TCP控制块,包含netconn、pcb和socket,并把这三者绑定在了一条线上)
if (g_keepalive == 1)//如果一个连接上7200s后没有任何数据发送,则设置了这个选项的本端向对端发送keepalive保活报文
TCP_KEEPDILE 设置连接上如果没有数据发送的话,多久后发送keepalive探测分组,单位是秒
TCP_KEEPINTVL 前后两次探测之间的时间间隔,单位是秒
TCP_KEEPCNT 关闭一个非活跃连接之前的最大重试次数
if (bearerParas->nCid == 0x11)netif = getEtherNetIf(bearerParas->nCid);// wifielsenetif = getGprsNetIf(nSim, bearerParas->nCid); //GPRS
//硬件接口设置
ip4_addr_t *ip_addr = (ip4_addr_t *)netif_ip4_addr(netif);CFW_TCPIP_SOCKET_ADDR stLocalAddr = {0,};stLocalAddr.sin_len = 0;stLocalAddr.sin_family = CFW_TCPIP_AF_INET;if (tcpipParas->uProtocol == CFW_TCPIP_IPPROTO_UDP)stLocalAddr.sin_port = htons(gClocalport[nMuxIndex].udp_port);elsestLocalAddr.sin_port = htons(gClocalport[nMuxIndex].tcp_port);stLocalAddr.sin_addr.s_addr = ip_addr->addr;
SOCKET保存到本地,进行CFW_TcpipSocketBind (lwip_bind)//绑定
lwip_bind会调用netconn_bind(将IP和port绑定到TCP控制块)
->lwip_netconn_do_bind->tcp_bind
iResult = CFW_TcpipInetAddr(tcpipParas->uaIPAddress);
调用inet_addr,将字符串转换为32位二进制网络字节序的IPV4地址
iResult = CFW_TcpipSocketConnect(tcpipParas->uSocket, &nDestAddr, SIZEOF(CFW_TCPIP_SOCKET_ADDR));调用lwip_connect(打印出主机地址和端口号)->netconn_connect(将服务器端的IP地址和端口号与本地的netconn结构绑定)->lwip_netconn_do_connect->tcp_connect(向主机端发起连接,设置状态为SYN_SENT)->tcp_output(找出需要发送的东西,并发送它)->tcp_output_segment(填充TCP头部确认号,设置通告串口,发送具体数据段)->ip_output_if->ip4_output_if->ip4_output_if_opt->ip4_output_if_opt_src->ip4_debug_print(打印出IP包)
发送请求包完成,lwip层进行协议运转,
lwip_tcp_event收到LWIP_EVENT_CONNECTED的时候表示连接完成,sys_post_event_to_APP(EV_CFW_TCPIP_SOCKET_CONNECT_RSP, conn->socket, 0, cfw_socket_map[conn->socket].userParam);
向应用层上报EV_CFW_TCPIP_SOCKET_CONNECT_RSP事件,AT_TCPIP_Connect中socket时会回调tcpip_rsp,当tcpip_rsp收到EV_CFW_TCPIP_SOCKET_CONNECT_RSP时,会调用tcpip_connect_done,表示三次握手完成,链接成功建立.
定时器的实现: LWIP 中实现了两个定时器处理函数: tcp_fasttmr ()和 tcp_slowtmr ()。 tcp_fasttmr 函数是每 250ms 调用一次; tcp_slowtmr 函数每 500ms 调用一次。超时重传功能是在 tcp_slowtmr 中实现的。