文章目录

  • netty版本
  • 长连接
  • ChannelGroup


netty版本

  1. netty版本:io.netty:netty-all:4.1.33.Final

长连接

  1. 由于服务器和客户端的交互全是通过Channel(通道)的读写操作来实现的,所以这个应用逻辑层必须要做的一件事就是对Channel的管理,另外和Channel紧密相关的就是客户端设备和用户,那么到底是用设备绑定Channel,还是用用户绑定Channel,这个问题须得考虑清楚。
  2. 第一种,使用长连接通道不断开的形式进行通信,也就是服务器和客户端的通道一直处于开启的状态。如果服务器性能足够好,并且我们的客户端数量也比较少的情况下,是适合使用长连接的通道。
  3. 第二种,采用短连接方式,一次性批量提交数据,也就是我们会把数据保存在本地临时缓冲区或者临时表里。当达到数量时,就进行批量提交;或者通过定时任务轮询提交。这种情况是有弊端的,就是无法做到实时传输。如果应用程序对实时性要求不高,可以考虑使用。
  4. 第三种,采用一种特殊的长连接。特殊在哪里呢?在指定的某一时间之内,服务器与某台客户端没有任何通信,则断开连接,如果断开连接后,客户端又需要向服务器发送请求,那么再次建立连接。这里有点CachedThreadPool的味道。
  5. Netty中的每一个Socket连接就是一个Channel,只需要将所有连接的客户端Channel加到ChannelGroup对象channels中去,只需在逻辑处理中调用channels对象的writeAndFlush()方法将消息发送出去就行了

ChannelGroup

  1. Netty提供了ChannelGroup来用于保存Channel组ChannelGroup是一个线程安全的Channel集合,它提供一些对Channel的批量操作。当一个TCP连接关闭后,对应的Channel会自动从ChannelGroup移除,所以不需要手动去移除关闭的Channel
  2. 当有新的客户端连接到服务器,将对应的Channel加入到一个ChannelGroup中,当发布者发布消息时,服务器可以将消息通过ChannelGroup写入到所有客户端。
class TcpServerHandler extends ChannelInboundHandlerAdapter {
    
    	// ChannelGroup用于保存所有连接的客户端,注意要用static来保证只有一个ChannelGroup实例,否则每new一个TcpServerHandler都会创建一个ChannelGroup
    	private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    
    	@Override
    	public void channelActive(ChannelHandlerContext ctx) {
    		channels.add(ctx.channel()); // 将新的连接加入到ChannelGroup,当连接断开ChannelGroup会自动移除对应的Channel
    	}
    
    	@Override
    	public void channelRead(ChannelHandlerContext ctx, Object msg) {
    		channels.writeAndFlush(msg + "\r\n"); // 接收到消息后,将消息发送到ChannelGroup中的所有客户端
    	}
    
    	@Override
    	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    		// cause.printStackTrace();  
    		ctx.close();
    	}
    }