简体   繁体   English

ESP32 和 Kotlin 服务器之间的套接字延迟不一致

[英]Inconsistent socket latency between ESP32 and Kotlin server

Context:语境:

  • I have a Server (Mac Mini) and a Client (ESP32) that are communicating through a socket connection via the WifiClient class.我有一个服务器(Mac Mini)和一个客户端(ESP32),它们通过 WifiClient class 通过套接字连接进行通信。
  • The server is connected to the router by ethernet and the client is connected to the router using 2.4ghz WiFi.服务器通过以太网连接到路由器,客户端使用 2.4ghz WiFi 连接到路由器。
  • The server is written in Kotlin and is using the default Java socket implementation.服务器使用 Kotlin 编写,并使用默认的 Java 套接字实现。
  • The client is to assign the colors to Neopixel LEDs (led 1 and 2, respectively) using the FastLED library.客户将使用 FastLED 库将 colors 分配给 Neopixel LED(分别为 LED 1 和 2)。

For the sake of testing, the server is sending FF0000|FF0000 and 0000FF|0000FF (as strings) in an alternating pattern 60 times per second.为了测试,服务器每秒以 60 次交替模式发送FF0000|FF00000000FF|0000FF (作为字符串)。 This test works well because if the color updates at a rate of 60 times per second, the LEDs should look purple.这个测试效果很好,因为如果颜色以每秒 60 次的速度更新,LED 应该看起来是紫色的。 If the system is performing poorly, then I will see the individual colors.如果系统表现不佳,那么我会看到个别 colors。

Client Github Repo and Server Github Repo for additional context. 客户端 Github 存储库服务器 Github 存储库以获取更多上下文。

The Problem:问题:

I am very clearly seeing alternating blue, red, and purple.我非常清楚地看到交替的蓝色、红色和紫色。 This tells me that there are performance problems somewhere, but there are also brief moments where it performs as expected.这告诉我某处存在性能问题,但也有短暂的时刻按预期执行。

My Findings:我的发现:

I've been logging the times it takes to read out each message on the client:我一直在记录读取客户端上每条消息所需的时间:

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();
}

The times that print out are generally good, but I get periodic spikes about 10 times per second.打印出来的时间通常很好,但我每秒会收到大约 10 次的周期性峰值。 I have added a log to Pastebin here .在这里向 Pastebin 添加了一个日志。

I thought that the clients buffer was becoming saturated when I first saw this.当我第一次看到这个时,我认为客户端缓冲区已经饱和了。 I then lowered the message rate on the server to 2 times per second, but I still was seeing significant variation in message times.然后我将服务器上的消息速率降低到每秒 2 次,但我仍然看到消息时间的显着变化。 That log is here .那个日志在这里

I printed out the system time whenever the server sent a message to verify that it is being written at the correct rate.每当服务器发送消息以验证它是否以正确的速率写入时,我都会打印出系统时间。 Updating 2 times a second consistently yields gaps of 500ms, so I think it is reasonable to rule out the server.每秒更新 2 次始终会产生 500 毫秒的间隙,因此我认为排除服务器是合理的。 This would suggest that the issue is either the transit time or ESP32 (considering the server is posting at the specified intervals).这表明问题出在传输时间或 ESP32(考虑到服务器以指定的时间间隔发布)。

The ping between the two devices is 5-10ms when the socket is not active, but is 50-400+ when the socket is active...even if I'm not sending any messages back and forth.当套接字不活动时,两个设备之间的 ping 为 5-10 毫秒,但当套接字处于活动状态时为 50-400+……即使我没有来回发送任何消息。 Heck - it's that high even when I completely comment out the client's while loop (ie it immediately returns an empty string).哎呀-即使我完全注释掉客户端的while循环(即它立即返回一个空字符串),它也这么高。

The Question:问题:

It would seem that my central problem is the latency between the devices while the socket is active.看来我的中心问题是套接字处于活动状态时设备之间的延迟。 At the very least - the ping increase when the socket is active seems within the ballpark of the latency increase while attempting to read the next command.至少 - 套接字处于活动状态时的 ping 增加似乎在尝试读取下一个命令时延迟增加的范围内。

Do you think that the socket is the primary problem here?您认为套接字是这里的主要问题吗? If so - why?如果是这样 - 为什么?

It seems strange to me that such a massive latency increase would occur simply by virtue of a socket being active...especially when not transmitting any sizable data back and forth.对我来说似乎很奇怪,仅仅由于套接字处于活动状态就会发生如此巨大的延迟增加……尤其是在不来回传输任何大量数据的情况下。

I set the performance preferences and disable TCP delay on the server's socket connection based on this thread .我基于此线程设置了性能首选项并禁用了服务器套接字连接上的 TCP 延迟。

In the server code I set the ServerSocket performance preferences to 1, 2, 0.在服务器代码中,我将 ServerSocket 性能首选项设置为 1、2、0。

val server = ServerSocket(9999)
server.setPerformancePreferences(1, 2, 0)

I also disabled TCP delay on the connection.我还在连接上禁用了 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() }
}

This appeared to make a drastic improvement.这似乎取得了巨大的进步。 There are definitely moments where the lights are (mostly) purple.肯定有一些时候灯光(大部分)是紫色的。 It does seem like the latency degrades over time and the connection may die, so there is still fine tuning to be done.似乎延迟会随着时间的推移而降低,并且连接可能会中断,因此仍然需要进行微调。

So - I think this issue is mostly solved (with some fine tuning).所以 - 我认为这个问题基本上已经解决了(通过一些微调)。 That said, I would still appreciate any further input that anybody has.也就是说,我仍然会感谢任何人提供的任何进一步的意见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM