ESP8266--学习笔记(五)TCP通信--TCP-Server

TCP Server模式

  • ESP8266 工作在station模式下,需确认ESP8266已经分配到IP地址,在启用server侦听
  • ESP8266 工作在Soft-AP 模式下,可以直接启动server侦听

TCP Server模式配置流程:

  • 根据工作协议初始化espconn参数
  • 注册连接成功的回调函数和连接失败重新连接的回调函数(espconn_regist_connectcb和espconn_regist_reconcb)
  • 调用espconn_accept侦听TCP连接
  • TCP连接成功后,在连接成功的回调函数(espconn_connect_callback)中,注册接收数据的回调函数,发送数据成功的回调函数和断开连接的回调函数(espconn_regist_recvcb,espconn_regist_sentcb和espconn_regist_disconcb)

一样的借用WiFi扫描连接的基础代码,并在WiFi连接的功能函数里面添加TCP连接功能,WiFi连接在主入口函数中的业务代码

void ICACHE_FLASH_ATTR Wifi_conned(void *arg){
    static uint8 count=0;
    struct ip_info info; //用于获取IP地址的信息
    uint8 status;
    os_timer_disarm(&connect_timer);
    count++;
    status=wifi_station_get_connect_status();
    if(status==STATION_GOT_IP){
        os_printf("Wifi connect success!");

        const char remote_ip[4]={192,168,1,103};//用于存放本地IP地址,一定要是自己的电脑真实的本地IP地址
        wifi_get_ip_info(STATON_IF,&info);
        //my_station_init((struct ip_addr *)remote_ip,&info.ip,1025);//Client端初始化主函数
        my_server_init(&info.ip,1213);//Server端初始化主函数
        return;
    }else{
        if(count>=7){
        os_printf("Wifi connect fail!");
        return;
        }
    }
    os_timer_arm(&connect_timer,2000,NULL);
}

user_main.c的所有代码:

* user_main.c
 *
 *  Created on: 2017脛锚3脭脗14脠脮
 *      Author: yuanlifu
 */
#include "ets_sys.h"
#include "driver/uart.h"
#include "user_main.h"
#include "user_interface.h"
#include "client.h"
#include "server.h"

ETSTimer connect_timer;
void ICACHE_FLASH_ATTR Wifi_conned(void *arg){
    static uint8 count=0;
    uint8 opmode;
    struct ip_info info; //用于获取IP地址的信息
    uint8 status;
    os_timer_disarm(&connect_timer);
    count++;
    status=wifi_station_get_connect_status();
    if(status==STATION_GOT_IP){
        os_printf("Wifi connect success!");

        const char remote_ip[4]={192,168,1,103};//用于存放本地IP地址,一定要是自己的电脑真实的本地IP地址
        wifi_get_ip_info(STATON_IF,&info);
        opmode = wifi_get_opmode_default();
        os_printf("\r\n当前的工作模式:%d\r\n",opmode);
        //my_station_init((struct ip_addr *)remote_ip,&info.ip,1025);//Client端初始化主函数
        my_server_init(&info.ip,1213);//Server端初始化主函数
        return;
    }else{
        if(count>=7){
        os_printf("Wifi connect fail!");
        return;
        }
    }
    os_timer_arm(&connect_timer,2000,NULL);
}

void ICACHE_FLASH_ATTR scan_done(void *arg,STATUS status){

     uint8 ssid[33];
      char temp[128];
      struct station_config stationConf;
      if (status == OK)
       {
         struct bss_info *bss_link = (struct bss_info *)arg;
         bss_link = bss_link->next.stqe_next;//ignore first

         while (bss_link != NULL)
         {
           os_memset(ssid, 0, 33);
           if (os_strlen(bss_link->ssid) <= 32)
           {
             os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
           }
           else
           {
             os_memcpy(ssid, bss_link->ssid, 32);
           }
           os_sprintf(temp,"+CWLAP:(%d,\"%s\",%d,\""MACSTR"\",%d)\r\n",
                      bss_link->authmode, ssid, bss_link->rssi,
                      MAC2STR(bss_link->bssid),bss_link->channel);
           os_printf("%s",temp);
           bss_link = bss_link->next.stqe_next;
         }
        os_memcpy(&stationConf.ssid, "MERCURY_2784", 32);
        os_memcpy(&stationConf.password, "123456789", 64);
        wifi_station_set_config_current(&stationConf);
        wifi_station_connect();
        os_timer_setfn(&connect_timer,Wifi_conned,NULL);
        os_timer_arm(&connect_timer,2000,NULL);
       }
       else
       {
     //     os_sprintf(temp,"err, scan status %d\r\n", status);
     //     uart0_sendStr(temp);
        os_printf("%s","Error");
       }
}
void to_scan(void)  { wifi_station_scan(NULL,scan_done); }

void user_init(){
    struct softap_config config;
        uint8 opmode;
        uart_init(115200,115200);
        wifi_set_opmode(0x03);//设置为AP模式
        opmode = wifi_get_opmode_default();
        os_printf("\r\n当前的工作模式:%d\r\n",opmode);

        wifi_softap_get_config(&config);
        os_memcpy(config.ssid,"ESP8266",strlen("ESP8266"));
        os_memcpy(config.password,"123456789",strlen("123456789"));
        config.ssid_len = strlen("ESP8266");
        wifi_softap_set_config(&config);

        system_init_done_cb(to_scan);//扫描WiFi需要系统初始化完成之后
}

void user_rf_pre_init(){

}

接下来就是编写TCP server的套路了

  • 根据工作协议初始化espconn参数
  • 注册连接成功的回调函数和连接失败重新连接的回调函数(espconn_regist_connectcb和espconn_regist_reconcb)
  • 调用espconn_accept侦听TCP连接
  • TCP连接成功后,在连接成功的回调函数(espconn_connect_callback)中,注册接收数据的回调函数,发送数据成功的回调函数和断开连接的回调函数(espconn_regist_recvcb,espconn_regist_sentcb和espconn_regist_disconcb)

server.h

/**
*server.h
**/
#ifndef APP_INCLUDE_SERVER_H
#define APP_INCLUDE_SERVER_H

#include "user_main.h"
#include "espconn.h"
#include "mem.h"

void my_server_init(struct ip_addr *local_ip,int port);

#endif/*APP_INCLUDE_SERVER_H*/

server.c

* server.c
 *
 *  Created on: 2017317日
 *      Author: yulifu
 */

#include "server.h"

void ICACHE_FLASH_ATTR server_recv(void *arg,
            char *pdata,
            unsigned short len){//接收数据的回调函数
        os_printf("收到PC发来的数据:%s\r\n",pdata);//将客户端发过来的数据打印出来
        espconn_sent((struct espconn *)arg,"发送已经收到\r\n",strlen("发送已经收到"));//往客户机发送数据
}
void ICACHE_FLASH_ATTR server_sent(void *arg){//发送数据成功的回调函数
    os_printf("发送数据成功!!\r\n");
}
void ICACHE_FLASH_ATTR server_discon(void *arg){//断开连接的回调函数
    os_printf("连接已经断开\r\n");
}

void ICACHE_FLASH_ATTR server_listen(void *arg){//服务器监听函数
    struct espconn *pespconn=arg;

    espconn_regist_recvcb(pespconn,server_recv);//注册一个接收数据的回调函数
    espconn_regist_sentcb(pespconn,server_sent);//注册一个发送数据成功的回调函数
    espconn_regist_disconcb(pespconn,server_discon);//注册一个断开连接的回调函数
}

void ICACHE_FLASH_ATTR server_recon(void *arg,sint8 err){//重新连接回调函数
    os_printf("连接错误,错误代码为:%s\r\n",err);//输出重新连接的错误代码
}

void ICACHE_FLASH_ATTR my_server_init(struct ip_addr *local_ip,int port){
    LOCAL struct espconn esp_conn;
    esp_conn.type=ESPCONN_TCP;
    esp_conn.state=ESPCONN_NONE;
    esp_conn.proto.tcp=(esp_tcp *)os_malloc(sizeof(esp_tcp));

    os_memcpy(esp_conn.proto.tcp->local_ip,local_ip,4);
    esp_conn.proto.tcp->local_port=port;


    //注册连接成功的回调函数和连接失败重新连接的回调函数
    espconn_regist_connectcb(&esp_conn,server_listen);//注册一个连接成功回调函数
    espconn_regist_reconcb(&esp_conn,server_recon);//注册一个连接失败重新连接回调函数


    espconn_accept(&esp_conn);
}

———————————————————————————

效果:
PC端:

ESP8266--学习笔记(五)TCP通信--TCP-Server_第1张图片

手机端APP效果:

ESP8266--学习笔记(五)TCP通信--TCP-Server_第2张图片

找到了一份ESP8266关于TCP通信的源码感觉还不错,怕忘记了就把它放在这里:
tcp.c

/*
 * tcp.c
 *
 *  Created on: 2017年3月23日
 *      Author: yuanlifu
 */
#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#include "mem.h"
#include "espconn.h"
#include "driver/uart.h"
#include "tcp.h"
typedef enum
{
  teClient,
  teServer
}teType;
typedef struct
{
    BOOL linkEn;
  BOOL teToff;
    uint8_t linkId;
    teType teType;
    uint8_t repeaTime;
    uint8_t changType;
    uint8 remoteIp[4];
    int32_t remotePort;
    struct espconn *pCon;
}linkConType;

typedef struct
{
  BOOL linkEn;
  BOOL teToff;
  uint8_t linkId;
  teType teType;
  uint8_t repeaTime;
  struct espconn *pCon;
} espConnectionType;

linkConType pLink;
espConnectionType user_contype;
static struct espconn *pTcpServer;
//os_event_t    procTaskQueue[procTaskQueueLen];
bool Connect_break;
bool Send_Flag;
/*
 * 函数名:void Wifi_AP_Init()
 * 功能wifi_ap初始化
 */
void WIFIAPInit()
{
    struct softap_config apConfig;
    /***************************模式设置************************************/
         if(wifi_set_opmode(SOFTAP_MODE)){          //  设置为AP模式

         }else{

         }
    /***************************名字设通道置************************************/
          os_bzero(&apConfig, sizeof(struct softap_config));
          wifi_softap_get_config(&apConfig);
          apConfig.ssid_len=7;                      //设置ssid长度
          os_strcpy(apConfig.ssid,"213联盟");         //设置ssid名字
          os_strcpy(apConfig.password,"12345678");  //设置密码
          apConfig.authmode =3;                     //设置加密模式
          ETS_UART_INTR_DISABLE();                  //关闭串口中断
          wifi_softap_set_config(&apConfig);        //配置
          ETS_UART_INTR_ENABLE();                   //打开串口
}
/*
 *函数名:void TcpServer_Listen_Recv(void *arg, char *pdata, unsigned short len)
 *功能:接收监听函数
 */
void TcpServer_Listen_Recv(void *arg, char *pdata, unsigned short len)
{
    uart0_sendStr(pdata);
}
/*
 * 函数名:void TcpServer_Listen_Recb(void *arg, sint8 errType)
 * 功能:连接监听函数
 */
void TcpServer_Listen_recon_cb(void *arg, sint8 errType)
{
    struct espconn *pespconn = (struct espconn *)arg;
      linkConType *linkTemp = (linkConType *)pespconn->reverse;
      Connect_break=0;
}
/*
 * 函数名:void Tcp_Server_Listen_discon_cb(void *arg)
 * 功能:正常断开时监听函数
 */
void Tcp_Server_Listen_discon_cb(void *arg)
{
      struct espconn *pespconn = (struct espconn *) arg;
      linkConType *linkTemp = (linkConType *) pespconn->reverse;
      Connect_break=0;
}
/*
 * 函数名:void Tcp_Server_Listen_sent_cb(void *arg)
 * 功能:发送成功监听函数
 */
void Tcp_Server_Listen_sent_cb(void *arg)
{
      struct espconn *pespconn = (struct espconn *) arg;
     linkConType *linkTemp = (linkConType *) pespconn->reverse;
     Send_Flag=0;
}
/*
 * 函数名:void TcpServer_Listen_PCon(void *arg)
 * 功能:手机连入AP监听函数
 */
void TcpServerListen_PCon(void *arg)
{
    struct espconn *pespconn = (struct espconn *)arg;
      pLink.teToff = FALSE;
      pLink.linkId = 1;
      pLink.teType = teServer;
      pLink.repeaTime = 0;
      pLink.pCon = pespconn;
      pespconn->reverse = &pLink;
      espconn_regist_recvcb(pespconn, TcpServer_Listen_Recv);                           //注册接收监听函数
      espconn_regist_reconcb(pespconn, TcpServer_Listen_recon_cb);                      //注册连接监听函数
      espconn_regist_disconcb(pespconn, Tcp_Server_Listen_discon_cb);                   //注册正常断开时监听函数
      espconn_regist_sentcb(pespconn, Tcp_Server_Listen_sent_cb);                       //注册发送成功监听函数

}
/*
 * 函数名:void WIFI_Server_MODE()
 * 功能:设置服务器模式
 */
void WIFIServerMode(void)
{
        espconn_tcp_set_max_con(1);                                         //设置TCP连接的最大多少
        pTcpServer = (struct espconn *)os_zalloc(sizeof(struct espconn));
        pTcpServer->type = ESPCONN_TCP;                                     //TCP服务
        pTcpServer->state = ESPCONN_NONE;                                   //状态
        pTcpServer->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
        pTcpServer->proto.tcp->local_port = 8888;                           //断开号
        espconn_regist_connectcb(pTcpServer, TcpServerListen_PCon);
        espconn_accept(pTcpServer);
        espconn_regist_time(pTcpServer, 180, 0);                            //设置超时断开时间 单位s


}
/*
 * 函数名:void WIFI_TCP_SendNews(unsigned char *dat)
 * 功能:像TCP服务器发送消息
 */
void WIFI_TCP_SendNews(unsigned char *dat,uint16 len)
{
    espconn_sent(pLink.pCon,dat,len);
}
/*void SendTask(os_event_t *events)
{
    struct station_info *pstation_info=wifi_softap_get_station_info();
        if((pstation_info!=NULL)&&(Connect_break==1)){
            if(Send_Flag==0){
                Send_Flag=1;
            WIFI_TCP_Send(xReceive,xLen);
            }else{

                uart0_sendStr("bus");
            }
        }else{
            Send_Flag=0;
            uart0_sendStr("NO device");
        }
        xLen=0;
}
void Task_Init()
{
//  uart_init(BIT_RATE_9600,BIT_RATE_9600);
     system_os_task(SendTask, procTaskPrio, procTaskQueue, procTaskQueueLen);
}*/

tcp.h

/*
 * tcp.h
 *
 *  Created on: 2017年3月23日
 *      Author: yuanlifu
 */

#ifndef APP_USER_TCP_H_
#define APP_USER_TCP_H_

void WIFIAPInit();
void WIFIServerMode(void);
void TcpServerListen_PCon(void *arg);
void WIFI_TCP_SendNews(unsigned char *dat,uint16 len);
//void Task_Init();

#endif /* APP_USER_TCP_H_ */

你可能感兴趣的:(C,ESP8266)