【发布时间】:2012-12-27 04:10:01
【问题描述】:
我有一个在 Netty 上工作的服务器。客户端发送一些握手消息和服务器回复。这些是小消息,没有问题。
但是,当服务器尝试发送一些大消息(每个大小为 131139 字节)时,似乎正在发送它们,ChannelFuture 的 isSuccess() 返回 true 和 getCause() 返回 @ 987654325@。但是,客户端永远不会得到完整的消息,只有第一条消息的第一个 4097 字节。在 4 或 5 条消息之后,netty 停止尝试发送新消息。
我在发送消息之前正在阅读频道的isWritable()(它总是返回true)。只有当ChannelFutureListener 的operationComplete 被触发时,才会尝试下一条消息。消息写入通道后,日志显示“INTEREST_CHANGED”事件被抛出两次,isWritable 更改为false,然后立即更改为true。但是消息永远不会到达客户端。
INFO [New I/O worker #7] (HashSender.java:33) - Attempting send a message: 0
INFO [New I/O worker #7] (HashSender.java:68) - Is channel writable: true
INFO [New I/O worker #7] (FrameLengthPrepender.java:46) - outgoing packet lenght: 131139
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: true
INFO [New I/O worker #7] (HashSender.java:16) - Message Successfully sent. Channel isDone: true, success: true, cancelled: false, error: null
INFO [New I/O worker #7] (HashSender.java:33) - Attempting send a message: 1
INFO [New I/O worker #7] (HashSender.java:68) - Is channel writable: true
INFO [New I/O worker #7] (FrameLengthPrepender.java:46) - outgoing packet lenght: 131139
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: false
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: true
INFO [New I/O worker #7] (HashSender.java:16) - Message Successfully sent. Channel isDone: true, success: true, cancelled: false, error: null
INFO [New I/O worker #7] (HashSender.java:33) - Attempting send a message: 2
INFO [New I/O worker #7] (HashSender.java:68) - Is channel writable: true
INFO [New I/O worker #7] (FrameLengthPrepender.java:46) - outgoing packet lenght: 131139
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: false
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: true
INFO [New I/O worker #7] (HashSender.java:16) - Message Successfully sent. Channel isDone: true, success: true, cancelled: false, error: null
INFO [New I/O worker #7] (HashSender.java:33) - Attempting send a message: 3
INFO [New I/O worker #7] (HashSender.java:68) - Is channel writable: true
INFO [New I/O worker #7] (FrameLengthPrepender.java:46) - outgoing packet lenght: 131139
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: false
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: true
INFO [New I/O worker #7] (HashSender.java:16) - Message Successfully sent. Channel isDone: true, success: true, cancelled: false, error: null
INFO [New I/O worker #7] (HashSender.java:33) - Attempting send a message: 4
INFO [New I/O worker #7] (HashSender.java:68) - Is channel writable: true
INFO [New I/O worker #7] (FrameLengthPrepender.java:46) - outgoing packet lenght: 131139
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: false
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: true
INFO [New I/O worker #7] (HashSender.java:16) - Message Successfully sent. Channel isDone: true, success: true, cancelled: false, error: null
INFO [New I/O worker #7] (HashSender.java:33) - Attempting send a message: 5
INFO [New I/O worker #7] (HashSender.java:68) - Is channel writable: true
INFO [New I/O worker #7] (FrameLengthPrepender.java:46) - outgoing packet lenght: 131139
INFO [New I/O worker #7] (ClientHandler.java:32) - [id: 0xdbb48b90, /192.168.0.3:60105 => /192.168.0.4:25025] INTEREST_CHANGED
INFO [New I/O worker #7] (ClientHandler.java:33) - Is channel writable: false
谁能告诉我为什么消息没有通过?
更新:它实际上是第一条消息的 4097 字节。标记数据包长度的前 4 个字节我没有计算。
更新:如果传出的数据包长度小于或等于 4097 字节,则一切正常。仅当数据包大于 4097 字节时,Netty 才会中断。它是 4097,而不是 4096。它会响铃吗?
【问题讨论】:
-
频道兴趣变化事件无需担心。 Netty 3.x 为每个通道维护一个带有高水位标记的内部写入缓冲区。这表示等待刷新到操作系统缓冲区的数据量。如果未完成的数据超过此值,则通道设置为不可写。默认值为 64K,因此您的大消息会立即触发频道兴趣更改事件。一旦数据被刷新到系统缓冲区,Netty 就会再次将通道设置为可写。我认为消息正在发送。您能提供客户的详细信息吗?
-
客户端是用c++编写的。它是一个非常成熟的代码,我正在重写服务器(最初是阻塞而不是异步的)。我很确定,每当发送大消息时,客户端只会收到第一条消息的前 4093 个字节。
-
更新:它实际上是第一条消息的 4097 字节。标记数据包长度的前 4 个字节我没有计算。
-
我又进行了一些实验,发现如果传出的数据包长度小于或等于4097字节,则一切正常。仅当数据包大于 4097 字节时,Netty 才会中断。它是 4097,而不是 4096。它会响铃吗?