一个关于Netty client program 的问题

W
WhereIsMyGCU
楼主 (未名空间)

这个版上有用过Netty的牛人吗?

现在在用Netty 开发一个小的客户和服务器程序。这两个程序的通信协议是用TLS。
TLS是channelpipeline里面的第一个handler:
pipe.addFirst("SSL", sslHandler)。现在这两个程序可以互相发送/接收数据。

我的问题是关于客户端 (client, not server)的早期数据发送。在客户端程序里面,
channelActive(ChannelHandlerContext ctx)被调用以后, ctx就可以被拿来用了。
理论上这时就可以发送数据了。但是实践发现, 这时的TCP连接是准备好了,但是TLS
的handshake 还没有完成。 如果这时发送数据,数据会无声无息的丢掉。这个很烦人。

TLS的handshake在channelRead(ChannelHandlerContext ctx, Object msg)被调用的时候(即收到一个数据包时)是完成了的。 但是这个程序是客户端,它应当先发送数据给
服务器(而不是等待数据)。为了防止发送数据丢失, 在客户端程序里面, 我试图先检测TLS的状态:
SSLEngine sslEngine = sslhandler.engine();
HandshakeStatus sslStatus = sslEngine.getHandshakeStatus();
if (sslStatus == HandshakeStatus.FINISHED || sslStatus == HandshakeStatus.
NEED_WRAP || sslStatus == HandshakeStatus.NOT_HANDSHAKING) {
...

发现这个方法不是很理想, 有时还是丢数据。反而是加一个固定的延时等待handshake结束更保险些。但是固定延时也不完全保险,特别是客户端必须同时开很多连接到很多服务器的时候。

这个问题有没有更好的解决办法? (我的Netty版本是Netty 4.1.36-Final)

谢谢!

T
TeacherWei

没用过netty。
但是明显你逻辑有问题

只有sslStatus == HandshakeStatus.FINISHED 以后,你才能读写socket。
其他状态你只能等。

netty肯定有sslStatus的callback。

你想想看,这么大的项目,怎么可能像你说的那样扯蛋?
f
fantasist

需要的大概是这个:https://netty.io/4.0/api/io/netty/handler/ssl/SslHandler.
html#handshakeFuture--
现在高级的语言基本都不用你自己检查状态,“HandshakeStatus.FINISHED”这种东西是implementation detail,用户自己引用不仅容易出错,版本升级还会带来兼容性问
题。callback是王道,一般只需要自己定义onSuccess和onFailure。Modern C++都这么写了,效率高很多。

n
netghost

不熟悉java,但是你總得connect吧。connect呢?

【 在 WhereIsMyGCU (LifeIsTough) 的大作中提到: 】
: 这个版上有用过Netty的牛人吗?
: 现在在用Netty 开发一个小的客户和服务器程序。这两个程序的通信协议是用TLS。 : TLS是channelpipeline里面的第一个handler:
: pipe.addFirst("SSL", sslHandler)。现在这两个程序可以互相发送/接收数据。
: 我的问题是关于客户端 (client, not server)的早期数据发送。在客户端程序里面,
: channelActive(ChannelHandlerContext ctx)被调用以后, ctx就可以被拿来用了。
: 理论上这时就可以发送数据了。但是实践发现, 这时的TCP连接是准备好了,但是
TLS
: 的handshake 还没有完成。 如果这时发送数据,数据会无声无息的丢掉。这个很烦
人。
: TLS的handshake在channelRead(ChannelHandlerContext ctx, Object msg)被调用的时
: 候(即收到一个数据包时)是完成了的。 但是这个程序是客户端,它应当先发送数据给
: ...................

W
WhereIsMyGCU

多谢。

你的这个是正解,跟Netty的event-driven 的设计思路相符。程序改正后表现好很多了。

【 在 fantasist (一) 的大作中提到: 】
: 需要的大概是这个:https://netty.io/4.0/api/io/netty/handler/ssl/SslHandler.
: html#handshakeFuture--
: 现在高级的语言基本都不用你自己检查状态,“HandshakeStatus.FINISHED”这种东西
: 是implementation detail,用户自己引用不仅容易出错,版本升级还会带来兼容性问
: 题。callback是王道,一般只需要自己定义onSuccess和onFailure。Modern C++都这么
: 写了,效率高很多。