上期介绍了Arduino的基本知识,今天直接上实例来给大家讲解TCPServer和TCPClient。看看他们到底是何方圣神。
1.TCP协议
TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,它在原有IP协议的基础上,增加了确认重发滑动窗口和复用/解复用等机制。
1.1TCP/IP的背景历史
1.2 TCP/IP协议分层模型
上图列出了TCP/IP与OSI分层之间的大概关系,可以看出,TCP/IP与OSI在分层模块上稍有区别。OSI参考模型注重“通信协议必要的功能是什么”,而TCP/IP则更强调“在计算机上实现协议应该开发哪种程序”。
现在再来看看主机A向主机B发送一封电子邮件,在TCP/IP模型下的处理过程:
分组数据包经过以太网的数据链路时的大致流程如下图所示:
1.3 主要特点
TCP有如下特点:
- TCP提供客户和服务器的连接。
- TCP提供可靠性。(数据的可靠投递或故障的可靠通知)并不能保证数据一定会被对方端点接收。
- TCP通过给所发数据的每一个字节关联一个序列号进行排序。
- TCP提供流量控制。TCP总是能告诉对象端它能够接收多少字节的数据,这成为通告窗口。该窗口在任何时刻都指出接收缓冲区中的可用空间,从而确保发送端发送的数据不会溢出接收缓冲区。
- TCP连接是全双工的。
2.如何理解TCPServer和TCPClient
其实从他的名称中就很容易了解他的意思:
TCPServer = TCP(传输控制协议)+Server(服务端)
TCPServer = TCP(传输控制协议)+Client(客户端)
2.1 Server&Client之间挥手握手图示
如上图所示,可以看出Client和Server之间的通信过程为:
新建连接三次握手->数据传输->断连接四次挥手
3.ESP8266中做TCPServer
我们先理清一下思路:
- 首先初始化WIFI(STA或者AP模式都可以)在这里我们使用STA模式。
- 然后建立TCPServer
3.1 使用STA模式连接WIFI
在第一节的时候就介绍过WIFI的三种模式,今天就上代码使用STA模式连接WIFI。
- 创建一个wifi账号、密码的常量,方便个人操作
const char * ssid = "DIRECT-37-HP Laser 136w"; //wifi账号 const char * pwd = "SoF1PMiKZ7"; //wifi密码 String Local_IP = ""; //获取当前匹配的IP地址
- 创建一个获取WiFi的函数
void setup() { Serial.begin(115200); //在115200波特率开启串口 pinMode(4, OUTPUT); //在开机时让灯输出也能让自己清楚的看到ESP8266是否在正常运行 digitalWrite(4, LOW); delay(1000); digitalWrite(4, HIGH); delay(1000); GETwifi(); //因为连接WIFI的步骤只需要执行一次,所以放在setup函数中即可 } void loop() { } /** * 获取Wifi信息 */ int GETwifi() { WiFi.mode(WIFI_STA); //WIFI模式设置为客户端STA模式 WiFi.begin(ssid,pwd); //连接wifi Serial.print("\nConnect to"); //向串口打印数据,方便我们调试程序 Serial.print(ssid); Serial.print("\n"); //连接WIFI while (WiFi.status() != WL_CONNECTED) //如果WIFI的status不等于连接上的状态 { delay(500); Serial.print("."); } if (WiFi.status() == WL_CONNECTED) //如果WIFI的status等于连接上的状态 { Serial.println("\nConnected success\n"); Local_IP = WiFi.localIP().toString(); //向串口打印出当前被分配到的IP地址 Serial.print("IP is:"); Serial.print(Local_IP); } else { Serial.printf("\nConnected failed\n"); } }
其实为了方便大家调试程序,我还是建议大家多多在串口输出数据。
3.2 建立TCPServer
在ESP8266中有WIFIServer
库用于TCP协议物联网通讯。
通过WIFIServer
库,我们可以使用ESP8266开发板建立网络服务器,从而允许其他网络设备以及物联网设备通过TCP协议访问并实现物联网信息交流。
3.2.1 WiFiServer库
3.2.2 WiFiServer代码实战
//最大连接数为1 WiFiServer server(80); //新建一个端口为80的服务器 WiFiClient serverClients[MAX_SRV_CLIENTS]; //新建一个大小为MAX_SRV_CLIENTS的客户端数组 String Local_IP = ""; //获取当前匹配的IP地址 String tcp_str = ""; //TTCP接收到的信息 void setup() { server.begin(); //启动服务器 server.setNoDelay(true); //停止小包合并发送,加上后才正常些 Serial.println("Server started"); uint8_t sstatus = server.status(); //获取当前TCP状态 Serial.print("server.status :"); Serial.println(sstatus); } void loop() { TCP_Server(); //循环运行服务器处理 } void TCP_Server() { uint8_t i; if (server.hasClient()){ //判断当前是否有客户端 for(i = 0; i < MAX_SRV_CLIENTS; i++){ //查找空闲或者断开连接的客户端,并置为可用 if (!serverClients[i] || !serverClients[i].connected()){ //如果数组中的某一项没有连接 if(serverClients[i]) serverClients[i].stop(); //如果有空闲连接,则断开连接 serverClients[i] = server.available(); //加入连接的客户端 Serial.print("New client: "); Serial.println(i); continue; } } //若没有可用客户端,则停止连接 WiFiClient serverClient = server.available(); serverClient.stop(); } //检查客户端的数据 for(i = 0; i < MAX_SRV_CLIENTS; i++){ if (serverClients[i] && serverClients[i].connected()){ if(serverClients[i].available()){ //从Telnet客户端获取数据,并推送到URAT端口 tcp_str =""; while(serverClients[i].available()) { tcp_str += (char)serverClients[i].read(); } Serial.print(tcp_str); Serial.print('\n'); } } } }
4.Windows下C#手柄+ESP8266+STC8A控制小车实战
- 效果(数据处理没有加入滤波,会有误差)
- 通过串口线连接ESP8266获取当前连接的IP:
Connect toDIRECT-37-HP Laser 136w ....... Connected success IP is:192.168.223.100 Server started server.status :1
- 打开自己粗略写的上位机填上TCP信息,确保电脑连接到同一个网络下后点击Connect连接TCPServer
- 连接到设备后下位机会将OLED显示自动跳转到TCP手柄控制数据界面。
- 选择控制设备,这里我选择手柄控制,检测到手柄信息后会自己连接到设备。
- 手柄在PC上测试流畅度
- 手柄在单片机上测试流畅度
Referance
2.http://www.mcublog.cn/esp8266/2019_11/fuwuqitcptongxin/
3.https://www.cnblogs.com/edisonchou/p/5987827.html