[英]Netty failing to read bytes from server when write fails due to socket close by server
网络版本:4.0.10.Final
我已经使用Netty编写了客户端和服务器。 这是客户端和服务器执行的操作。
服务器:
客户:
我已经架设了客户端和服务器。 我发现写入错误消息后服务器正在关闭连接。 在错误消息之后编写良好消息时,客户端开始看到断开的管道错误。 这是因为服务器检测到错误消息,并以错误消息和关闭的套接字响应。 仅在使用侦听器完成写操作之后,才关闭连接。 客户端不总是从服务器读取错误消息。 客户端中的较早步骤(2)在I / O线程中执行。 这导致在K次实验中收到的错误消息所占的百分比确实很低(<10%)。 将步骤(2)移动到单独的线程后,%达到(70%)。 无论如何都不是准确的。 如果由于管道中断而导致写入失败,netty是否触发通道读取?
更新1 :我正在澄清并回答此处提出的任何问题,因此每个人都可以在一个地方找到所提出的问题/澄清。 “您写的一条错误消息将导致重置,然后是您已经知道不会通过的好消息,并试图读取可能被丢弃的响应。对我来说这没有任何意义一切”-来自EJP
-在现实世界中,服务器可能会由于客户端事先不知道的任何原因而将其视为不良。 为简化起见,我说过客户端故意发送一条错误消息,导致服务器重置。 我希望发送所有好的消息,即使总消息中有坏消息也是如此。
我正在做的事情类似于Apple Push Notification Service实现的协议。
如果消息不正确,请写入错误消息(6个字节),将其刷新,关闭套接字,并且不要读取套接字中的任何未读消息。 否则,继续阅读消息。
这将导致连接重置,客户端将其视为Unix,Linux等中的损坏管道。
写完N条好消息后,写一条坏消息并继续写M条好消息。
那将遇到刚才提到的管道破裂错误。
此过程在单独的线程中发生。
为什么? NIO和Netty的全部要点是您不需要额外的线程。
我发现写入错误消息后服务器正在关闭连接。
嗯,这就是您所说的,所以做到了。
在错误消息之后编写良好消息时,客户端开始看到断开的管道错误。
就像我说的。
这是因为服务器检测到错误消息,并以错误消息和关闭的套接字响应。
正确。
客户端不总是从服务器读取错误消息。
由于连接重置。 重置后,挂起数据的传送将停止。
如果由于管道中断而导致写入失败,netty是否触发通道读取?
不,它会在数据或EOS到达时触发读取
但是,您的离奇的系统设计/协议使这种情况变得不可预知,即使不是不可能。 您正在写一条错误消息,它将导致重置,然后写出您已经知道不会通过的好消息,并尝试读取可能已被丢弃的响应。 这对我来说毫无意义。 您要在这里证明什么?
像其他人一样尝试请求-响应协议。
APN协议似乎很笨拙,因为它没有确认成功接收到通知。 相反,它只会告诉您遇到错误时已成功接收到哪些通知。 该协议假设您通常会发送格式正确的通知。
我建议您需要某种过期的缓存(LinkedHashMap可能在这里工作),并且需要将通知中的不透明标识符字段用作全局唯一的有序值。 序列号将起作用(但是,如果可以重新启动客户端,则需要坚持执行)。
每次生成APN
如果收到错误,则需要重新打开连接并重新发送映射中的所有APN,并使用比错误中报告的标识符更高的序列号。 这是相对容易的。 只需遍历图,删除序列号低于所报告序列号的任何APN。 然后按顺序重新发送其余的APN,将其替换为当前时间在地图中(即,您在重新发送APN时将其删除,然后使用新的当前时间重新插入地图中)。
您需要定期清除旧条目的地图。 如果发送格式错误的APN,则需要根据APN服务返回错误所需的时间来确定合理的时间长度。 我怀疑这将是几秒钟的事情(如果不是更快的话)。 例如,如果您每秒发送10个APN,并且您知道APN服务器肯定会在30秒内响应,则30秒的到期时间(每秒清除)可能是合适的。 只需沿着地图进行迭代,即可删除键的时间段小于System.currentTimeMillis()-30000(持续30秒的有效时间)的所有元素。 您需要适当地同步线程。
我会捕获任何由写入引起的IOException,并将您尝试写入的APN放置在映射中并重新发送。
您无法解决的是真正的网络错误,由此您不知道APN服务是否收到了通知(或一堆通知)。 您是否要立即或在一段时间后重新发送受影响的APN,就必须根据服务的内容来做出决定。 如果您在一段时间后发送邮件,则需要在发送时给他们新的序列号。 这样,您就可以同时发送新的APN。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.