How does netty know that the client is actively disconnected, and the channelId appears at the same time, the problem of data confusion

This article has participated in the "Newcomer Creation Ceremony" event to start the road of gold creation together.


The first thing to know is that netty is multithreaded. It is based on Socket.

1: Previously, bloggers used List in netty to store channelId and uniquely identify it, but ignored one point, List is not safe. Especially in a multi-threaded environment, there will be a problem of data confusion.

2: For security reasons, the form of Map is adopted again. If it is only used to access channelId, there is definitely no problem. But what if multiple interfaces call this Map? Something seems wrong.

3: The environment on the blogger's side is an external network application, which pushes data to the internal network. The access to channelId here does not consider what cache to use for access, it is directly shared by static.

solution:

When connecting:

1: When there is a client connection, record the client's channelId.

2: Establish a connection and return a message

When disconnected:

1: The client actively disconnects the server and closes the stream.

2: Disconnect

 /**
  * 当有客户端连接时,handlerAdded会执行,就把该客户端的通道记录下来,加入队列
  * 连接第1步
  * @param ctx
  * @throws Exception
  */
 @Override
 public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
     Channel channel = ctx.channel();
     channels.add(channel);
     super.handlerAdded(ctx);
 }

 /**
  * 建立连接时,返回消息
  * 连接第2步
  * @param ctx
  * @throws Exception
  */
 @Override
 public void channelActive(ChannelHandlerContext ctx) throws Exception {
     Channel channel = ctx.channel();
     AttributeKey<String> host_channel_key = AttributeKey.valueOf("channel-host");
     Attribute<String> attr = channel.attr(host_channel_key);
     InetSocketAddress socketAddress = (InetSocketAddress) channel.remoteAddress();
     String host = socketAddress.getHostString();
     attr.set(host);
     log.debug("通道号:[{}],客户端:[{}]: 在线",channel.toString(), channel.remoteAddress());
     super.channelActive(ctx);

 }


/**
 * 客户端主动断开服务端的链接,关闭流
 * */
 @Override
 public void channelInactive(ChannelHandlerContext ctx) throws Exception {
     Channel channel = ctx.channel();
     log.debug("通道号:[{}],客户端:[{}]: 离线",channel.toString(), channel.remoteAddress());
     super.channelInactive(ctx);
 }
 
 /**
  * 断开连接 第2步
  *
  * @param ctx
  * @throws Exception
  */
 @Override
 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
     Channel channel = ctx.channel();
     channels.remove(channel);
     super.handlerRemoved(ctx);
     ctx.channel().close();
 }

复制代码

The most important step.

public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

Look at the add method in the DefaultChannelGroup class

image.png

Forget it, it's multithreaded or not. It depends on whether we can meet our current needs. Channel channel = ctx.channel(); channels.add(channel); So far we have put channelId where it should be.

Then we are back to the beginning: netty is it multi-threaded or not. The ability of bloggers is limited, and those who are interested can go and see for themselves.

Guess you like

Origin juejin.im/post/7085622256457482248