0. 前言
转载自我的古月居频道
上期介绍了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提供可靠性。(数据的可靠投递或故障的可靠通知)并不能保证数据一定会被对方端点接收。
3.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代码实战
#include <ESP8266WiFi.h>
#define MAX_SRV_CLIENTS 1 //最大连接数为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
- http://www.taichi-maker.com/homepage/iot-development/iot-dev-reference/esp8266-c-plus-plus-reference/wifiserver/
- http://www.mcublog.cn/esp8266/2019_11/fuwuqitcptongxin/
- https://www.cnblogs.com/edisonchou/p/5987827.html