在使用netty时,有时候会和客户端保持长链接,这个时候服务端既可以接受客户端消息也可以主动发送消息给服务端。我们只需要在服务端保存客户端的ChannelHandlerContext对象,必要的时候通过write和flush方法即可实现服务端和客户端的通信。以下为handler的代码,其他代码和普通的netty一样。
public class AcceptServerChannelHandler extends ChannelInboundHandlerAdapter {
public static Map<String, ChannelHandlerContext> ctxMap = new ConcurrentHashMap<String, ChannelHandlerContext>(16);
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.write("test");
ctxMap.put(keyId,ctx);
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.flush();
ctx.close();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
/**
* 服务端接收客户端发送过来的数据结束之后调用
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
super.channelReadComplete(ctx);
}
/**
* 客户端主动断开服务端的连接
* @param ctx
* @throws Exception
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
removeChannelMap(ctx);
super.channelInactive(ctx);
}
/**
* 移除已经失效的链接
* @param ctx
*/
private void removeChannelMap(ChannelHandlerContext ctx) {
for( String key :ctxMap.keySet()){
if(ctxMap.get(key)!=null && ctxMap.get(key).equals(ctx)){
ctxMap.remove(key);
}
}
}
public void sendMessage(String keyid){
ChannelHandlerContext ctx = ctxMap.get(keyid);
ctx.write("test");
ctx.flush();
//writeAndFlush在这里没生效,没找到原因
}
}