Nagle 算法的目的是通过合并一些小的发送消息,然后一次性发送所有的消息来减少通过网络发送的小数据包的tcp/ip流量。这种方法的缺点是延迟了单个消息的发送,直到一个足够大的包被组装。
6.1.4 close() —— 关闭TCP server
函数说明:
/**
* 关闭TCP server
*/
void close();
6.1.5 stop() —— 停止TCP server
函数说明:
/**
* 停止TCP server
*/
void stop();
注意点:
stop()和 close()是同样的功能,所以调用哪一个都没有问题;
void WiFiServer::stop() {
close();
}
6.1.1 status() ——返回TCP server状态
函数说明:
/**
* 返回TCP server状态
* @return wl_tcp_state tcp状态
*/
uint8_t status();
wl_tcp_state 包括:
//博主暂时没理解具体每一个怎么用
enum wl_tcp_state {
CLOSED
= 0,// 关闭
LISTEN
= 1,// 监听中
SYN_SENT = 2,
SYN_RCVD = 3,
ESTABLISHED = 4,// 建立连接
FIN_WAIT_1 = 5,
FIN_WAIT_2 = 6,
CLOSE_WAIT = 7,
CLOSING
= 8,
LAST_ACK = 9,
TIME_WAIT = 10
};
6.2 WiFiClient接入
6.2.1 available —— 获取有效的wificlient连接
函数说明:
/**
* 获取有效的wificlient连接
* @return 如果存在有效的wificlient连接,就返回WiFilient对象,如果没有那就返回一个无效的wificlient(connected等于false,开发者可以通过判断connected()
*/
WiFiClient available(uint8_t* status = NULL);
函数源码:
WiFiClient WiFiServer::available(byte* status) {
(void) status;
//判断是否有非空的连接对象
if (_unclaimed) {
WiFiClient result(_unclaimed);
_unclaimed = _unclaimed->next();
result.setNoDelay(_noDelay);
DEBUGV("WS:av\r\n");
return result;
}
optimistic_yield(1000);
//没有连接对象就返回无用的wificlient对象
return WiFiClient();
}
6.2.2 hasClient —— 判断是否有client连接
函数说明:
/**
* 判断是否有client连接
* @return bool 如果有client连接就返回true
*/
bool hasClient();
注意点:
开发者可以通过判断这个函数来判断是否有client连接,然后调用available() 方法来获取连接,这样拿到wificlient之后就可以调用wificlient的方法;
7. 实例操作
前面讲了这么多理论内容,接下来用几个例子来说明一下。
7.1 演示WiFiServer功能
例子介绍:
8266作为WiFiServer端,打开TCP调试助手,模拟TCP Client的请求。
例子源码:
/**
* Demo:
* 演示WiFiServer功能
* 打开TCP调试助手 模拟TCP client请求
* @author 单片机菜鸟
* @date 2019/09/04
*/
#include <ESP8266WiFi.h>
//定义最多多少个client可以连接本server(一般不要超过4个)
#define MAX_SRV_CLIENTS 1
//以下三个定义为调试定义
#define DebugBegin(baud_rate) Serial.begin(baud_rate)
#define DebugPrintln(message) Serial.println(message)
#define DebugPrint(message) Serial.print(message)
const char* ssid = "TP-LINK_5344";
const char* password = "6206908you11011010";
//创建server 端口号是23
WiFiServer server(23);
//管理clients
WiFiClient serverClients[MAX_SRV_CLIENTS];
void setup() {
DebugBegin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
DebugPrint("\nConnecting to ");
DebugPrintln(ssid);
uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < 20) {
delay(500);
}
if (i == 21) {
DebugPrint("Could not connect to");
DebugPrintln(ssid);
while (1) {
delay(500);
}
}
//启动server
server.begin();
//关闭小包合并包功能,不会延时发送数据
server.setNoDelay(true);
DebugPrint("Ready! Use 'telnet ");
DebugPrint(WiFi.localIP());
DebugPrintln(" 23' to connect");
}
void loop() {
uint8_t i;
//检测是否有新的client请求进来
if (server.hasClient()) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
//释放旧无效或者断开的client
if (!serverClients[i] || !serverClients[i].connected()) {
if (serverClients[i]) {
serverClients[i].stop();
}
//分配最新的client
serverClients[i] = server.available();
DebugPrint("New client: ");
DebugPrint(i);
break;
}
}
//当达到最大连接数 无法释放无效的client,需要拒绝连接
if (i == MAX_SRV_CLIENTS) {
WiFiClient serverClient = server.available();
serverClient.stop();
DebugPrintln("Connection rejected ");
}
}
//检测client发过来的数据
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected()) {
if (serverClients[i].available()) {
//get data from the telnet client and push it to the UART
while (serverClients[i].available()) {
//发送到串口调试器
Serial.write(serverClients[i].read());
}
}
}
}
if (Serial.available()) {
//把串口调试器发过来的数据 发送给client
size_t len = Serial.available();
uint8_t sbuf[len];
Serial.readBytes(sbuf, len);
//push UART data to all connected telnet clients
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected()) {
serverClients[i].write(sbuf, len);
delay(1);
}
}
}
}
测试结果:
7.2 演示web Server功能