nettyは、クライアントがアクティブに切断され、channelIdが同時に表示されることをどのようにして知るのでしょうか。これは、データの混乱の問題です。

この記事は、「新人クリエーションセレモニー」イベントに参加し、一緒にゴールドクリエーションの道を歩み始めました。


最初に知っておくべきことは、nettyはマルチスレッドであるということです。これはSocketに基づいています。

1:以前は、ブロガーはnettyでListを使用してchannelIdを保存し、それを一意に識別していましたが、1つのポイントを無視しました。Listは安全ではありません。特にマルチスレッド環境では、データの混乱の問題が発生します。

2:セキュリティ上の理由から、マップの形式が再び採用されます。channelIdにアクセスするためだけに使用される場合は、間違いなく問題はありません。しかし、複数のインターフェースがこのマップを呼び出す場合はどうなるでしょうか。何かがおかしいようです。

3:ブロガー側の環境は、データを内部ネットワークにプッシュする外部ネットワークアプリケーションです。ここでのchannelIdへのアクセスは、アクセスに使用するキャッシュを考慮せず、staticによって直接共有されます。

解決:

接続時:

1:クライアント接続がある場合は、クライアントのchannelIdを記録します。

2:接続を確立し、メッセージを返します

切断時:

1:クライアントはサーバーをアクティブに切断し、ストリームを閉じます。

2:切断

 /**
  * 当有客户端连接时,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();
 }

复制代码

最も重要なステップ。

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

DefaultChannelGroupクラスのaddメソッドを見てください

image.png

それを忘れてください、それはマルチスレッドであるかどうかです。それは私たちが現在のニーズを満たすことができるかどうかに依存します。Channel channel = ctx.channel();channels.add(channel);これまでのところchannelIdを本来あるべき場所に配置しました。

次に、最初に戻ります。nettyは、マルチスレッドかどうかです。ブロガーの能力は限られており、興味のある人は自分で見に行くことができます。

おすすめ

転載: juejin.im/post/7085622256457482248