java(或python)服务器有时未收到 TCP 数据
TCP data sometimes not received by java (or python) server
我正在开发一个由 arduino mkr1000 组成的系统,我想通过 wifi 将数据发送到本地网络中的 java 服务器程序 运行。
除主要部分外一切正常:服务器有时未收到 arduino 发送的数据...
我正在使用 arduino Wifi101 library 连接到我的 wifi,获取 WiFiClient
并发送数据。
以下代码只是演示问题的示例:
for (int i = 0; i < 3; ++i) {
Serial.println(F("Connecting to wifi"));
const auto status = WiFi.begin("...", "...");
if (status != WL_CONNECTED) {
Serial.print(F("Could not connect to WiFi: "));
switch (status) {
case WL_CONNECT_FAILED:
Serial.println(F("WL_CONNECT_FAILED"));
break;
case WL_DISCONNECTED:
Serial.println(F("WL_DISCONNECTED"));
break;
default:
Serial.print(F("Code "));
Serial.println(status, DEC);
break;
}
} else {
Serial.println(F("WiFi status: WL_CONNECTED"));
WiFiClient client;
if (client.connect("192.168.0.102", 1234)) {
delay(500);
client.print(F("Test "));
client.println(i, DEC);
client.flush();
Serial.println(F("Data written"));
delay(5000);
client.stop();
} else {
Serial.println(F("Could not connect"));
}
WiFi.end();
}
delay(2000);
}
java 服务器基于 Netty,但手动创建和读取 Socket
的结果相同。
测试代码非常标准,只有一个简单的输出(注意:在 Kotlin 中):
val bossGroup = NioEventLoopGroup(1)
val workerGroup = NioEventLoopGroup(6)
val serverFuture = ServerBootstrap().run {
group(bossGroup, workerGroup)
channel(NioServerSocketChannel::class.java)
childHandler(object : ChannelInitializer<NioSocketChannel>() {
override fun initChannel(ch: NioSocketChannel) {
ch.pipeline()
.addLast(LineBasedFrameDecoder(Int.MAX_VALUE))
.addLast(StringDecoder())
.addLast(object : ChannelInboundHandlerAdapter() {
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
println("msg = $msg")
ctx.close()
}
})
}
})
bind(port).sync()
}
arduino 表明一切正常(即每次迭代都将 Data written
写入串行控制台)但服务器有时会跳过个别消息。
在这些情况下,从 Netty 添加 LoggingHandler
告诉我:
11:28:48.576 [nioEventLoopGroup-3-1] WARN i.n.handler.logging.LoggingHandler - [id: 0x9991c251, L:/192.168.0.20:1234 - R:/192.168.0.105:63845] REGISTERED
11:28:48.577 [nioEventLoopGroup-3-1] WARN i.n.handler.logging.LoggingHandler - [id: 0x9991c251, L:/192.168.0.20:1234 - R:/192.168.0.105:63845] ACTIVE
在收到消息的情况下,它告诉我:
11:30:01.392 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] REGISTERED
11:30:01.394 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] ACTIVE
11:30:01.439 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] READ: 8B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 54 65 73 74 20 32 0d 0a |Test 2.. |
+--------+-------------------------------------------------+----------------+
11:30:01.449 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] CLOSE
11:30:01.451 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 ! R:/192.168.0.105:59927] READ COMPLETE
11:30:01.453 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 ! R:/192.168.0.105:59927] INACTIVE
11:30:01.464 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 ! R:/192.168.0.105:59927] UNREGISTERED
根据我的理解,这意味着确实收到了 TCP 数据包,但在错误情况下,来自 Netty 的 IO 线程正在等待读取 TCP 数据,但永远不会继续...
尝试使用基本的 python 服务器(只是等待连接并打印接收到的数据)时存在同样的问题。
我确认数据是通过在 Arch Linux 上使用 tcpflow
和参数 -i any -C -g port 1234
发送的。
我什至在 Windows 7 机器上尝试了服务器,结果相同(用 SmartSniff 确认的 TCP 数据包)。
奇怪的是,使用 java 服务器发送的数据始终可重复接收...
有没有人知道解决问题或至少如何诊断?
PS:也许重要的是要注意 tcpflow
(即 linux)我可以看到 TCP 数据包被重新发送到服务器。
这是否意味着服务器正在接收数据包但不发送 ACK?
SmartSniff 没有显示相同的行为(但也许我使用了错误的选项来显示重新发送的数据包)。
与此同时,我发送消息以确认收到另一条消息。如果未收到确认,则再次发送消息。
遇到同样问题的人:
在测试不同的东西时,我将电路板的 wifi 固件更新到最新版本 19.5.2
。从那以后,我没有注意到任何丢失的数据。也许这就是问题所在。
参见 Check WiFi101 Firmware Version and Firmware and certificates Updater。
注意: 我无法使用 Arduino IDE 将草图绘制到 运行,但使用 PlatformIO。
我正在开发一个由 arduino mkr1000 组成的系统,我想通过 wifi 将数据发送到本地网络中的 java 服务器程序 运行。
除主要部分外一切正常:服务器有时未收到 arduino 发送的数据...
我正在使用 arduino Wifi101 library 连接到我的 wifi,获取 WiFiClient
并发送数据。
以下代码只是演示问题的示例:
for (int i = 0; i < 3; ++i) {
Serial.println(F("Connecting to wifi"));
const auto status = WiFi.begin("...", "...");
if (status != WL_CONNECTED) {
Serial.print(F("Could not connect to WiFi: "));
switch (status) {
case WL_CONNECT_FAILED:
Serial.println(F("WL_CONNECT_FAILED"));
break;
case WL_DISCONNECTED:
Serial.println(F("WL_DISCONNECTED"));
break;
default:
Serial.print(F("Code "));
Serial.println(status, DEC);
break;
}
} else {
Serial.println(F("WiFi status: WL_CONNECTED"));
WiFiClient client;
if (client.connect("192.168.0.102", 1234)) {
delay(500);
client.print(F("Test "));
client.println(i, DEC);
client.flush();
Serial.println(F("Data written"));
delay(5000);
client.stop();
} else {
Serial.println(F("Could not connect"));
}
WiFi.end();
}
delay(2000);
}
java 服务器基于 Netty,但手动创建和读取 Socket
的结果相同。
测试代码非常标准,只有一个简单的输出(注意:在 Kotlin 中):
val bossGroup = NioEventLoopGroup(1)
val workerGroup = NioEventLoopGroup(6)
val serverFuture = ServerBootstrap().run {
group(bossGroup, workerGroup)
channel(NioServerSocketChannel::class.java)
childHandler(object : ChannelInitializer<NioSocketChannel>() {
override fun initChannel(ch: NioSocketChannel) {
ch.pipeline()
.addLast(LineBasedFrameDecoder(Int.MAX_VALUE))
.addLast(StringDecoder())
.addLast(object : ChannelInboundHandlerAdapter() {
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
println("msg = $msg")
ctx.close()
}
})
}
})
bind(port).sync()
}
arduino 表明一切正常(即每次迭代都将 Data written
写入串行控制台)但服务器有时会跳过个别消息。
在这些情况下,从 Netty 添加 LoggingHandler
告诉我:
11:28:48.576 [nioEventLoopGroup-3-1] WARN i.n.handler.logging.LoggingHandler - [id: 0x9991c251, L:/192.168.0.20:1234 - R:/192.168.0.105:63845] REGISTERED
11:28:48.577 [nioEventLoopGroup-3-1] WARN i.n.handler.logging.LoggingHandler - [id: 0x9991c251, L:/192.168.0.20:1234 - R:/192.168.0.105:63845] ACTIVE
在收到消息的情况下,它告诉我:
11:30:01.392 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] REGISTERED
11:30:01.394 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] ACTIVE
11:30:01.439 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] READ: 8B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 54 65 73 74 20 32 0d 0a |Test 2.. |
+--------+-------------------------------------------------+----------------+
11:30:01.449 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 - R:/192.168.0.105:59927] CLOSE
11:30:01.451 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 ! R:/192.168.0.105:59927] READ COMPLETE
11:30:01.453 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 ! R:/192.168.0.105:59927] INACTIVE
11:30:01.464 [nioEventLoopGroup-3-6] WARN i.n.handler.logging.LoggingHandler - [id: 0xd51b7bc3, L:/192.168.0.20:1234 ! R:/192.168.0.105:59927] UNREGISTERED
根据我的理解,这意味着确实收到了 TCP 数据包,但在错误情况下,来自 Netty 的 IO 线程正在等待读取 TCP 数据,但永远不会继续... 尝试使用基本的 python 服务器(只是等待连接并打印接收到的数据)时存在同样的问题。
我确认数据是通过在 Arch Linux 上使用 tcpflow
和参数 -i any -C -g port 1234
发送的。
我什至在 Windows 7 机器上尝试了服务器,结果相同(用 SmartSniff 确认的 TCP 数据包)。
奇怪的是,使用 java 服务器发送的数据始终可重复接收...
有没有人知道解决问题或至少如何诊断?
PS:也许重要的是要注意 tcpflow
(即 linux)我可以看到 TCP 数据包被重新发送到服务器。
这是否意味着服务器正在接收数据包但不发送 ACK?
SmartSniff 没有显示相同的行为(但也许我使用了错误的选项来显示重新发送的数据包)。
与此同时,我发送消息以确认收到另一条消息。如果未收到确认,则再次发送消息。
遇到同样问题的人:
在测试不同的东西时,我将电路板的 wifi 固件更新到最新版本 19.5.2
。从那以后,我没有注意到任何丢失的数据。也许这就是问题所在。
参见 Check WiFi101 Firmware Version and Firmware and certificates Updater。
注意: 我无法使用 Arduino IDE 将草图绘制到 运行,但使用 PlatformIO。