netty如何实现向客户端主动发送消息

需求场景:智能家居网关(以下简称gateway),需要和netty服务器通讯(以下简称netty),netty和gateway之间需要保持长连接(换句话说,netty和gateway之间都会主动给对方发送消息)
碰到的问题:netty作为服务器端如何主动的向gateway发送消息,我尝试当每个gateway连接到netty(TCP/IP)时使用一个map把该channelSocket的id和该channelSocket绑定在一起
@Override
publicvoidchannelActive(ChannelHandlerContextctx)throwsException{
Stringuuid=ctx.channel().id().asLongText();
GatewayService.addGatewayChannel(uuid,(SocketChannel)ctx.channel());
System.out.println("anewconnectcomein:"+uuid);
}
GatewayService其实就是一个ConcurrentHashMap
publicclassGatewayService{
privatestaticMapmap=newConcurrentHashMap<>();
publicstaticvoidaddGatewayChannel(Stringid,SocketChannelgateway_channel){
map.put(id,gateway_channel);
}
publicstaticMapgetChannels(){
returnmap;
}
publicstaticSocketChannelgetGatewayChannel(Stringid){
returnmap.get(id);
}
publicstaticvoidremoveGatewayChannel(Stringid){
map.remove(id);
}
}
我在服务器端尝试每间隔一段时间loop这个ConcurrentHashMap如果里面已经有绑定的channelSocket,就使用write方法向客户端发送消息
RunnablesendTask=newRunnable(){
@Override
publicvoidrun(){
sendTaskLoop:
for(;;){
System.out.println("taskisbeginning...");
try{
Mapmap=GatewayService.getChannels();
Iteratorit=map.keySet().iterator();
while(it.hasNext()){
Stringkey=it.next();
SocketChannelobj=map.get(key);
System.out.println("channelidis:"+key);
System.out.println("channel:"+obj.isActive());
obj.writeAndFlush("hello,itisServertestheaderping");
}
}catch(Exceptione){breaksendTaskLoop;}
try{
Thread.sleep(5000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
};
newThread(sendTask).start();
理论上客户端应该是可以接受到我发送的消息,但是我观察了一下源代码,发现writeAndFlush这个方法最终会被handler触发,于是我又在handler中覆写了write方法
@Override
publicvoidwrite(ChannelHandlerContextctx,Objectmsg,ChannelPromisepromise)throwsException{
System.out.println("writehandler");
ctx.writeAndFlush(msg);
}
可是最终结果客户端并没有收到任何消息,请问netty如何主动向客户端发送消息?
PIPIONE
浏览 6595回答 2
2回答

MMMHUHU

可以大概猜测到是服务端没有编码器,因此根本发不出去从贴出的代码里可以看到代码里往客户端发消息时有两种方式:obj.writeAndFlush("hello,itisServertestheaderping");和ctx.writeAndFlush(msg);//Object在netty里,进出的都是ByteBuf,楼主应确定服务端是否有对应的编码器,将字符串转化为ByteBuf。

临摹微笑

GatewayService这里保存channel的时候不需要强制转换成SocketChannel类型,拿到channel做writeAndFlush是没有问题的。为了进一步排查问题,可以这么做,1.对ctx.writeAndFlush(msg);的Promise结果做监听,比如ctx.writeAndFlush(msg).addListener(newChannelFutureListener(){@OverridepublicvoidoperationComplete(ChannelFuturefuture)throwsException{if(future.isSuccess()){//dosth}else{//dosth}}});2.注意客户端和服务端两边的编码器和解码器是否相同
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript