想做一个设备连上服务端之后,服务端可以主动向客户端推送的系统,开始学习。
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 的过程中被意外暂停,你可以延迟执行刷新操作,然后在迟些时候继续。
尝试1:根据上述,通过ChannelOutboundHandlerAdapter 延迟发送消息给客户端。
结果:
(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~