上一节说的是TCP客户端模式下的通信,这一节说一下服务器端模式下的通信,总体来说,代码是差不多的,只是关键地方有些调整。
另外,包括上一节在内,这两节的代码里,ESP8266的工作模式设置为了station+softap模式。但在进行TCP通信时,都是以station的身份通信。后面会说一下,如果以softap身份通信有什么注意事项。
还有就是,有的朋友留言问,如果想快速开发APP,实现手机和ESP8266的通信调试,一般怎么实现。就我个人,一般是在物联网后台上直接看数据,很少在手机上操作。有没有想过自己写APP?
有,确实想过,但还是之前提过的,我是个硬件工程师~自己写APP?跨度有点大,我倒是做过一些工作,研究过易安卓和安卓studio,感兴趣的可以试着从这两方便入手试试,或者有其它的,大家也可以留言。
好,继续。这里保留上一节引用的“TCP编程的服务器端一般步骤”,作为参考:
TCP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt(); * 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、开启监听,用函数listen();
5、接收客户端上来的连接,用函数accept();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
8、关闭监听;
因为步骤和上一节相似程度很高,所以我会做一些简化,如果有看不懂的地方,建议对比上一节内容。另外,学习类的东西,建议在电脑端打开,个人感觉手机上看的效果一般,只能看个大概。深度学习,个人还是习惯在电脑上进行。好,演示开始。
因为做了简化,步骤分为4步。
1、包含头文件
跟上一节一样,所以略过。
2、设置工作模式为station+ soft-ap模式,并连接到当前环境下的wifi
跟上一节一样,但是这次的代码加了一句。虽然设置为了station+ soft-ap模式,设置了AP名字和密码,但好像不用输入密码就能连接,这是因为没有设置加密模式:
config.authmode = AUTH_WPA_PSK; //加密模式
增加这一行之后,就可以了。更多信息建议看一下“softap_config”这个结构体的定义,里面比较详细。
3、确定TCP服务器端的参数,并初始化
我是谁——ESP8266,连接家里路由成功之后,会自动获得一个IP,这是服务器端IP
谁要和我连接——因为是在我电脑上使用网络调试助手模拟TCP客户端端,所以客户端端的IP是我电脑的IP:192.168.1.103
连接的端口——这里选1025.
struct ip_info info;
const char remote_ip[4]={192,168,1,103}; //TCP客户端IP
wifi_get_ip_info(STATION_IF,&info); //获取8266的WIFI信息
server_init((struct ip_addr *)remote_ip,&info.ip,1025);
可以看到,和上一节相比,函数名字变了,但其实内容大部分都一样:
{
LOCAL struct espconn esp_conn;
//初始化espconn参数
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);
os_memcpy(esp_conn.proto.tcp->remote_ip,remote_ip,4);
esp_conn.proto.tcp->local_port=port;
//注册连接成功回调函数和重新连接回调函数
espconn_regist_connectcb(&esp_conn,server_listen);
espconn_regist_reconcb(&esp_conn,server_recon);
//创建TCP server,建立监听
espconn_accept(&esp_conn);
}
不一样的地方,我用加粗和斜线的方式标了出来。先说:
espconn_accept(&esp_conn);
因为这个简单,上一节是TCP客户端,创建连接,所以用:
espconn_connect(&user_tcp_conn);
而这一节是服务器端,是一个等待别人来连接我的角色,所以要监听别人。
然后是回调函数server_listen,它的内容也和客户端不一样。具体区别看第4步。
4、定义连接成功的回调函数
函数内容如下:
struct espconn *pespconn=arg;
os_printf("\r\nconnect success!\r\n");
espconn_regist_recvcb(pespconn,server_recv);
espconn_regist_sentcb(pespconn,server_sent);
espconn_regist_disconcb(pespconn,server_discon);
客户端的函数代码如下:
struct espconn *pespconn=arg;
espconn_regist_recvcb(pespconn,user_tcp_recv_cb);
espconn_regist_sentcb(pespconn,user_tcp_sent_cb);
espconn_regist_disconcb(pespconn,user_tcp_discon_cb);
espconn_sent(pespconn,"hello,this is esp8266!",strlen("hello,this is esp8266!"));
不考虑printf的打印信息,创建的这三个回调函数,功能大部分基本是一样的。都是接收完成回调函数、发送完成回调函数和断开连接回调函数。区别在于客户端连接成功后会主动发送信息,而服务器端被动一些,收到信息后,才会根据需要有所返回。
那几个回调函数,功能大同小异,就不说了。所以除了这些,基本上就没什么区别了。感兴趣的童鞋,建议把代码下载下来,依次对比一下,这样可以有一个比较深的理解。
好,到此为止,程序修改完毕。
注:本例程里提到的大部分函数,都参照手册2c-esp8266_sdk_api_guide_cn_v1.5.4。
程序修改完成,保存、清理、编译、下载一条龙,然后重新上电。这里,需要借助串口助手和网络调试助手两个工具来查看效果。效果如下所示:
设置网络调试助手:
注意事项:需要等到ESP8266连接家里wifi成功以后,也就是串口助手打印出:Wifi connect success!之后,网络调试助手才能进行连接。
因为在此之前,TCP server端还没有初始化完成,这时候TCP客户端即便想连接,也找不到对象。
TCP连接成功之后,串口助手输出信息:connect success!
这时,手动从网络调试助手那里发送信息:MCU LOVER
可以看到串口助手打印出来,这说明ESP8266已经收到了。
这时,在网络调试助手这里点击“断开”,可以看到串口助手打印:TCP cliend disconnected!
说明连接断开成功(client 写成了 cliend,不要在意这些细节)。
最后,有的人可能会问,你说的这些步骤、工作流程都是怎么来的?不可能是瞎猜的吧?
确实,这个问题很关键,所有工作都要有一个明确的工作流程。其实答案还是在手册里:2c-esp8266_sdk_api_guide_cn_v1.5.4,第216页:
有了手册,再参考SDK里面的例程,基本就差不多了。还是那句话,多看手册。好,这一节说完了,欢迎大家动手尝试!
完整工程源码,请关注公众号:单片机爱好者,回复关键字:ESP8266,即可获取。