FreeRTOS下WIFI模块下的socket(四)
本章节主要涉及到最核心的4个任务一.串口接收并解析任务最核心//解析网络数据包 static void esp8266_recv_packet(PAT_Device ptDev) { Uart_Device *ptUARTDev ptDev-ptUARTDev; uint8_t data; int hw_socket 0; int len 0; int state 0; // 0:等待hw_socket, 1:等待len, 2:读取数据 int received 0; PAT_Socket ptSocket NULL; // IPD,link id,len:data while(1) { //读取串口数据 if(0 ! ptUARTDev-Read(ptUARTDev, (uint8_t *)data, portMAX_DELAY)) { return; } switch(state) { case 0: // 解析hw_socket { if(data ,) { state 1; // 切换到解析len状态, 根据hw_socket找到对应的PAT_Socket ptSocket get_socket_for_hw_socket(hw_socket); if(!ptSocket) return; // 找不到对应的socket continue; } if(data 0 data 9) { hw_socket hw_socket * 10 (data - 0); } break; } case 1: // 解析len { if(data :) { state 2; // 切换到读取数据状态 continue; } if(data 0 data 9) { len len * 10 (data - 0); } break; } case 2: // 读取数据 { if(received len) { if(ptSocket) { xQueueSend(ptSocket-recv_queue, data, 0); } } received; if(received len ptSocket) { // 释放信号量通知有新数据 xSemaphoreGive(ptSocket-at_packet_sem); return; } break; } default: { break; } } } } //核心结构 //接收数据任务 static void esp8266_parser(void *parameter) { PAT_Device ptDev (PAT_Device)parameter; Uart_Device *ptUARTDev ptDev-ptUARTDev; uint8_t data; int32_t len 0; uint8_t line[AT_LINE_BUF_SIZE1]; memset(line,0,sizeof(line)); len 0; while(1) { //读取串口数据 if(0 ! ptUARTDev-Read(ptUARTDev, data, portMAX_DELAY)) { continue; } line[len] data; if(len AT_LINE_BUF_SIZE) { len 0; } line[len] \0; //解析是否为网络数据 if(strstr((const char *)line, IPD,)) { esp8266_recv_packet(ptDev); len 0; memset(line,0,sizeof(line)); continue; } //处理AT命令响应数据 if(data \n) // 检测到换行符 { if(ptDev-resp_line_counts AT_RESP_MAX_LINE) { //清除当前行的数据 memset(ptDev-resp[ptDev-resp_line_counts], 0, AT_RESP_BUF_SIZE); //保存当前行到resp数组 memcpy(ptDev-resp[ptDev-resp_line_counts], line, (len1)); /* 每行后面的\0也被记录了 */ ptDev-resp_len[ptDev-resp_line_counts] (len1); ptDev-resp_line_counts; } printf(line:%d , %s \r\n,ptDev-resp_line_counts,line); len 0; } //检测结束标志 if(strstr((const char *)line, OK\r\n) || strstr((const char *)line, ERROR\r\n)) { if(strstr((const char *)line, OK\r\n)) { ptDev-resp_status AT_RESP_OK; } else { ptDev-resp_status AT_RESP_ERROR; } //释放信号量通知命令完成 xSemaphoreGive(ptDev-at_resp_sem); len 0; memset(line,0,sizeof(line)); } } }二.TCP-Client#define SERVER_IP 192.168.0.199 #define SERVER_PORT 8888 #define WIFI_NAME Programmers #define WIFI_PASSWD 100asktech void tcp_client_test_task(void *parameter) { at_init(uart2); // 先假定使用UART2连接ESP8266 while(1) { if(0 at_connect_ap(WIFI_NAME, WIFI_PASSWD)) { break; } vTaskDelay(1000); } int iSocketClient; iSocketClient (int)socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in tSocketServerAddr; tSocketServerAddr.sin_family AF_INET; tSocketServerAddr.sin_port htons(SERVER_PORT); /* host to net, short */ int rc inet_pton(tSocketServerAddr.sin_family, SERVER_IP, (tSocketServerAddr.sin_addr)); if(rc 0) { return ; } memset(tSocketServerAddr.sin_zero, 0, 8); int iRet connect(iSocketClient, (const struct sockaddr*)tSocketServerAddr, sizeof(struct sockaddr)); if(-1 iRet) { return ; } char ucSendBuf[60]{helloword\r\n}; send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0); while(1) { uint8_t ucRecvBuf[300]; int iRecvLen; memset(ucRecvBuf,0,sizeof(ucRecvBuf)); iRecvLen recv(iSocketClient, (char*)ucRecvBuf, 200, 0); if(iRecvLen 0) { ucRecvBuf[iRecvLen] \0; printf(recv tcp data: %s\r\n,ucRecvBuf); send(iSocketClient, ucRecvBuf, strlen((char*)ucRecvBuf), 0); } // // // int iSendLen send(iSocketClient, (char*)ucSendBuf, (int)strlen((char*)ucSendBuf), 0); // // // if(iSendLen 0) // { // closesocket(iSocketClient); // return ; // } // } }三.TCP-Server#define WIFI_NAME Programmers #define WIFI_PASSWD 100asktech #define SERVER_PORT 8888 #define BACKLOG 4 void tcp_server_test_task(void *parameter) { int iSocketServer; struct sockaddr_in tSocketServerAddr; int iSocketClient; struct sockaddr_in tSocketClientAddr; uint32_t iAddrLen; int msg_cnt 0; int iClientNum 0; at_init(uart2); // 先假定使用UART2连接ESP8266 while(1) { if(0 at_connect_ap(WIFI_NAME, WIFI_PASSWD)) { break; } vTaskDelay(1000); } //分配socket iSocketServer (int)socket(AF_INET, SOCK_STREAM, 0); //绑定ip和port tSocketServerAddr.sin_family AF_INET; tSocketServerAddr.sin_port htons(SERVER_PORT); tSocketServerAddr.sin_addr.s_addr INADDR_ANY; //这里ip地址复制了INADDR_ANY memset(tSocketServerAddr.sin_zero, 0, 8); bind(iSocketServer, (const struct sockaddr*)tSocketServerAddr, sizeof(struct sockaddr)); //开始监听 listen(iSocketServer, BACKLOG); while(1) { iAddrLen sizeof(tSocketClientAddr); iSocketClient (int)accept(iSocketServer, (struct sockaddr*)tSocketClientAddr, (socklen_t *)iAddrLen); vTaskDelay(1000); if((-1) ! iSocketClient) { char ip[20]; inet_ntop(AF_INET, tSocketClientAddr.sin_addr, ip, 20); printf(Get connect from client %d : %s\n, iClientNum, ip); msg_cnt 0; while(1) { int iRecvLen; char ucRecvBuf[512]; char uc_send_Buf[128]; iRecvLen recv(iSocketClient, (char*)ucRecvBuf, 512, 0); if(iRecvLen 0) { msg_cnt; ucRecvBuf[iRecvLen] \0; printf(Get Msg From Client %d : %s\r\n, iClientNum, ucRecvBuf); memset(uc_send_Buf,0,sizeof(uc_send_Buf)); snprintf(uc_send_Buf, 128, GetMsg cnt %d\r\n, msg_cnt); send(iSocketClient, uc_send_Buf, strlen(uc_send_Buf), 0); } else { closesocket(iSocketClient); break; } } } } }四.UDP#define UDP_REMOTE_IP 192.168.0.199 #define UDP_REMOTE_PORT 7777 #define UDP_LOCAL_IP 192.168.0.128 #define UDP_LOCAL_PORT 8888 #define UDP_Recv_Max_Len 512 #define WIFI_NAME Programmers #define WIFI_PASSWD 100asktech void udp_test_task(void *parameter) { int iSocketServer; struct sockaddr_in tSocketLocalAddr; struct sockaddr_in tSocketRemoteAddr; int msg_cnt 0; at_init(uart2); // 先假定使用UART2连接ESP8266 while(1) { if(0 at_connect_ap(WIFI_NAME, WIFI_PASSWD)) { break; } vTaskDelay(1000); } uint8_t acRecvBuf[UDP_Recv_Max_Len2]{0}; uint8_t Send_Buf[128]{0}; //分配socket iSocketServer (int)socket(AF_INET, SOCK_DGRAM, 0); //分配ESP8266 tSocketLocalAddr.sin_family AF_INET; tSocketLocalAddr.sin_port htons(UDP_LOCAL_PORT); tSocketLocalAddr.sin_addr.s_addr INADDR_ANY; memset(tSocketLocalAddr.sin_zero, 0, 8); tSocketRemoteAddr tSocketLocalAddr; tSocketRemoteAddr.sin_port htons(UDP_REMOTE_PORT); int rc inet_pton(tSocketRemoteAddr.sin_family, UDP_REMOTE_IP, (tSocketRemoteAddr.sin_addr)); if(rc 0) { return ; } memset(tSocketRemoteAddr.sin_zero, 0, 8); //绑定esp8266的port连接时候需要 int iRet bind(iSocketServer, (const struct sockaddr*)tSocketLocalAddr, sizeof(struct sockaddr)); if((-1) iRet) { printf(bind error!\n); return ; } //连接 iRet connect(iSocketServer, (const struct sockaddr*)tSocketRemoteAddr, sizeof(struct sockaddr)); if((-1) iRet) { printf(connect error!\n); return ; } while(1) { socklen_t iAddrLen sizeof(tSocketRemoteAddr); printf(udp wait recv\n); int iRecvLen recvfrom(iSocketServer, acRecvBuf, UDP_Recv_Max_Len, 0, (struct sockaddr*)tSocketRemoteAddr, (socklen_t *)iAddrLen); if(iRecvLen 0 iRecvLen UDP_Recv_Max_Len) { acRecvBuf[iRecvLen] \0; char ip[20]; inet_ntop(AF_INET, tSocketRemoteAddr.sin_addr, ip, 20); printf(Get Msg From %s : %s\n, ip, acRecvBuf); memset(Send_Buf,0,sizeof(Send_Buf)); snprintf((char *)Send_Buf, (sizeof(Send_Buf)-1), GetMsg %d, msg_cnt); iAddrLen sizeof(tSocketRemoteAddr); sendto(iSocketServer, Send_Buf,strlen((char *)Send_Buf), 0, (struct sockaddr*)tSocketRemoteAddr, iAddrLen); printf(udp send ok\n); } else if(iRecvLen 0) { vTaskDelay(1000); } else { printf(udp recv len:%d \r\n,iRecvLen); } } //closesocket(iSocketServer); //return ; }五.总结整体的系统框架很重要在第一章中有讲到。核心结构体包括AT_Deive、AT_Socket、Uart_Devie接着就是分层管理包括接口层、适配层、esp8266模块驱动层、AT命令层、uart驱动层、应用层。其中还要注意的一点就是软件socket和硬件socket,两者是不同的。