c++ - ESP32 和 Kotlin 服务器之间的套接字延迟不一致
问题描述
语境:
- 我有一个服务器(Mac Mini)和一个客户端(ESP32),它们通过 WifiClient 类通过套接字连接进行通信。
- 服务器通过以太网连接到路由器,客户端使用 2.4ghz WiFi 连接到路由器。
- 服务器是用 Kotlin 编写的,并使用默认的 Java 套接字实现。
- 客户端将使用 FastLED 库将颜色分配给 Neopixel LED(分别为 LED 1 和 2)。
为了测试,服务器每秒以交替模式发送FF0000|FF0000
和0000FF|0000FF
(作为字符串)60 次。这个测试效果很好,因为如果颜色以每秒 60 次的速度更新,LED 应该看起来是紫色的。如果系统表现不佳,那么我将看到各个颜色。
客户端 Github 存储库和服务器 Github 存储库以获取更多上下文。
问题:
我非常清楚地看到交替的蓝色、红色和紫色。这告诉我某处存在性能问题,但也有短暂的时刻按预期执行。
我的发现:
我一直在记录读取客户端上每条消息所需的时间:
std::string SocketManager::getNextCommand()
{
unsigned long start = micros();
// TODO: Flush isn't working
// flush(): fail on fd 56, errno: 11, "No more processes"
// client.flush();
// We need to read in our next command; wait until command is available.
String message;
while (client.connected() && message.length() == 0)
{
message = client.readStringUntil('\n');
}
unsigned long end = micros();
Serial.print("Time: ");
Serial.println(end - start);
return message.c_str();
}
打印出来的时间通常很好,但我每秒会收到大约 10 次的周期性峰值。我在这里向 Pastebin 添加了一个日志。
当我第一次看到这个时,我认为客户端缓冲区已经饱和了。然后我将服务器上的消息速率降低到每秒 2 次,但我仍然看到消息时间的显着变化。那个日志在这里。
每当服务器发送消息以验证它是否以正确的速率写入时,我都会打印出系统时间。每秒更新 2 次始终会产生 500 毫秒的间隙,因此我认为排除服务器是合理的。这表明问题出在传输时间或 ESP32(考虑到服务器以指定的时间间隔发布)。
当套接字不活动时,两个设备之间的 ping 为 5-10 毫秒,但当套接字处于活动状态时为 50-400+……即使我没有来回发送任何消息!哎呀-即使我完全注释掉客户端的while循环(即它立即返回一个空字符串),它也这么高。
问题:
看来我的中心问题是套接字处于活动状态时设备之间的延迟。至少 - 套接字处于活动状态时的 ping 增加似乎在尝试读取下一个命令时延迟增加的范围内。
您认为套接字是这里的主要问题吗?如果是这样 - 为什么?
对我来说似乎很奇怪,仅仅由于套接字处于活动状态就会发生如此巨大的延迟增加……尤其是在不来回传输任何大量数据的情况下。
解决方案
我基于此线程设置了性能首选项并禁用了服务器套接字连接上的 TCP 延迟。
在服务器代码中,我将 ServerSocket 性能首选项设置为 1、2、0。
val server = ServerSocket(9999)
server.setPerformancePreferences(1, 2, 0)
我还禁用了连接上的 TCP 延迟。
while (true) {
val client = server.accept()
println("Client connected: ${client.inetAddress.hostAddress}")
client.soTimeout = 1000
client.tcpNoDelay = true;
// Run client in it's own thread.
thread { ClientHandler(client).run() }
}
这似乎取得了巨大的进步。肯定有一些时候灯光(大部分)是紫色的。似乎延迟会随着时间的推移而降低,并且连接可能会中断,因此仍然需要进行微调。
所以 - 我认为这个问题基本上已经解决了(通过一些微调)。也就是说,我仍然会感谢任何人提供的任何进一步的意见。
推荐阅读
- mysql - 如何解决 CentOS 8 中的这个 Mysql2 gem 错误?
- python - 为什么允许列表附加自身?
- python - 在 Pandas 中对 MultiIndex 进行分组
- excel - 在一个范围内的特定单元格中输入条件值,解锁另一个范围内的另一个特定单元格(VBA,范围偏移)
- angular - Angular 8 - 为 HTTP API 调用设置代理
- amazon-web-services - 有没有办法为多个脚本指定一个提供者?
- scrollview - 嵌套的 ScrollView SwiftUI
- reactjs - 反应:在 config-overrides.js 文件中为多个 html 文件添加多个入口点
- amazon-web-services - AWS S3 存储桶到 Route 53
- c++ - c ++在copy ctor的帮助下重载=运算符