我来学Netty之推送消息给客户端

想做一个设备连上服务端之后,服务端可以主动向客户端推送的系统,开始学习。

1.服务器处理类

i. 服务器事件处理类 

EchoServerHandler扩展io.netty.channel.ChannelInboundHandlerAdapter类,重写下面三个方法,当然,可以根据需要重写更多的方法: 

channelRead: 服务端收到客户端发来的数据 

channelReadComplete: 服务端读取客户端数据完毕 

exceptionCaught: 发生异常,比如客户端关闭连接时 
 

服务器时间处理类

2.疑问1,ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter之间的差别

为什么要分ChannelInboundHandlerAdapter(SimpleChannelInboundHandler)和ChannelOutboundHandlerAdapter(SimpleChannelOutboundHandler)?二者的区别是什么?

答:我已知的是二者的处理顺序,先处理In再处理Out。。

3.尝试1,使用ChannelOutboundHandlerAdapter 

ChannelOutboundHandler 提供了出站操作时调用的方法。这些方法会被 Channel, ChannelPipeline, 和 ChannelHandlerContext 调用。

ChannelOutboundHandler 另个一个强大的方面是它具有在请求时延迟操作或者事件的能力。比如,当你在写数据到 remote peer 的过程中被意外暂停,你可以延迟执行刷新操作,然后在迟些时候继续。

ChannelOutboundHandlerAdapter

尝试1:根据上述,通过ChannelOutboundHandlerAdapter 延迟发送消息给客户端。

OutboundHandle的api

结果:

(1)……不行,必须建一个客户端程序,在客户端跑。。

(2)初步成功,在ChannelInboundHandlerAdapter的 channelRead里响应客户端,发送命令给客户端。

(3)接下来,尝试在ChannelOutboundHandlerAdapter里给客户端回应,OK。

参照https://blog.csdn.net/u013252773/article/details/21195593里写的,在ChannelInboundHandlerAdapter里调用write,会然后会执行ChannelOutboundHandlerAdapter里write方法里的内容,然后再跳转回ChannelInboundHandlerAdapter继续执行后面的内容。

4.尝试调用保存了的Channel主动给设备下发内容

成功了!

不过不知道这种方法对不对,对于很多客户端连接会不会出问题。但至少目前实验过是可行的。后面贴一下代码。

(1)在继承ChannelInboundHandlerAdapter的类里的channelActive保存channel

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //连接上时执行
//        ConnectionInfo connectionInfo = ctx.channel()
//                .attr(OBDServerStarter.ATTR_KEY_CONNECTION_INFO)
//                .get();

//        if(connectionInfo != null){
            String uuid = ctx.channel().id().asLongText();
            ChannelMap.addTimeServerChannel(uuid, ctx.channel());
            System.out.println("A new connect come in: " + uuid);
//        }
//        else{
//            System.out.println("ConnectInfo is null");
//        }

    }

其中,ChannelMap:

import io.netty.channel.Channel;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ChannelMap {
    private static Map<String, Channel> channelMap = new ConcurrentHashMap<String, Channel>();

    public static void addTimeServerChannel(String id, Channel sc){
        channelMap.put(id, sc);
        System.out.println("size = "+channelMap.size());
    }

    public static Map<String, Channel> getAllChannels(){
        return channelMap;
    }

    public static Channel getTimeServerChannel(String id){
        return channelMap.get(id);
    }

    public static  void removeTimeServerChannel(String id){
        channelMap.remove(id);
    }

}

(2)在需要的地方获取channel向设备推送消息

 @RequestMapping("/deviceoperate")
    public  R deviceOperate(@RequestBody JSONObject params){
        String proContent = params.getString("proContent");
        JSONArray uuidList = params.getJSONArray("uuid");
        System.out.println(uuidList);
        System.out.println(proContent);
        for (int i = 0; i < uuidList.size(); i++) {
            Channel ch = ChannelMap.getTimeServerChannel(uuidList.get(i).toString());
            Frock f = FrameParser.frockMap.get(uuidList.get(i));
            ByteBuf byteCont = FrameParser.FrameFormat(1, proContent, f.getFrockMac());
            ch.writeAndFlush(byteCont);
        }

        return R.ok();
    }

可推送成功。

第一次发博客,求不喷,有意见建议可以提。

OVER~

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值