netty自定义channel id
netty自定义channel id、netty custom channel id
搞搞netty时发现默认的id很长,无法直接自定义。
于是我网上搜索了search一下,发现没有相关文章,那就自己看看源码手撸一个实现。这难不倒拥有7年代码经验的我,通过本文章你能大概学到如何根据源码定制功能。
通过netty官网说明唯一id:https://netty.io/wiki/new-and-noteworthy-in-4.1.html
全局唯一通道ID
每个频道现在都有一个全局唯一的ID,该ID由以下内容生成:
优选全局唯一的MAC地址(EUI-48或EUI-64),
当前进程ID,
系统#currentTimeMillis()
系统#nanoTime()
随机32位整数
顺序递增的32位整数
可以使用信道获得信道的ID.id()方法。
默认的id是这样的:通道id:a85e45fffec07f9b-00002454-00000000-084db96c90765225-d150e0b4
虽然很唯一,但不符合我们的系统,应该将它自定义。
一、自定义ID试调源码过程
我是基于netty 4.1.79.Final 2022年8月12日最新版本。
首先看id的实现接口:IDEA中按Ctrl + Alt + O 搜索 channel ID

应该就是这个了ChannelId接口了,接着看他的实现类

应该就是默认的实现了
观察到id为空时他就会new一个

接着看一下哪里用他生成:
此时我们发现是一个构造类用到了他AbstractChannel,AbstractChannel应该就是所有管道类的父类。

他的构造方法中也newId()了

他就是在这里吧ID给生成出来:

框架开发一般规则/套路:不直接使用构造类,那么我们看看他的继承使用情况:

太多了,我们不知道哪个会加载。
回到我们的客户端初始化类,看看能不能在初始化配置时找到自定义他的地方:

此时发现打印的是class io.netty.channel.socket.nio.NioSocketChannel这个类,恰好对应上面的NioSocketChannel处理
NioSocketChannel这个是客户端的管道处理类,默认是使用socket协议。恰好发现它是继承了AbstractChannel,
二、走查源码自定义结果
那应该就是通过自定义NioSocketChannel这个类进行自定义id生成。
三、实现自定义
通过上面的结果,我们通过继承NioSocketChannel来实现自定义id生成:使用UUID
import io.netty.channel.ChannelId;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.UUID;
/**
* @author lingkang
* Created by 2022/8/12
*/
public class MyNioSocketChannel extends NioSocketChannel {
protected ChannelId newId() {
ChannelId channelId = new ChannelId() {
@Override
public String asShortText() {
return UUID.randomUUID().toString();
}
@Override
public String asLongText() {
return UUID.randomUUID().toString();
}
@Override
public int compareTo(ChannelId o) {
return 0;
}
};
return channelId;
}
}
客户端初始化那就是用我们集成自定义的类

运行结果:

这个自定义是正确的,所以服务端也能按照上面的思路进行自定义。
四、完整代码:
import io.netty.channel.ChannelId;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.UUID;
/**
* @author lingkang
* Created by 2022/8/12
*/
public class MyNioSocketChannel extends NioSocketChannel {
protected ChannelId newId() {
ChannelId channelId = new ChannelId() {
@Override
public String asShortText() {
return UUID.randomUUID().toString();
}
@Override
public String asLongText() {
return UUID.randomUUID().toString();
}
@Override
public int compareTo(ChannelId o) {
return 0;
}
};
return channelId;
}
}
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import top.lingkang.flychat.common.MsgBody;
import top.lingkang.flychat.common.code.RpcDecoder;
import top.lingkang.flychat.common.code.RpcEncoder;
import top.lingkang.flychat.server.ServerHandler;
import top.lingkang.flychat.server.ServerInit;
import java.util.Date;
/**
* @author lingkang
* Created by 2022/8/12
*/
public class Test01Server {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
// 当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。
.option(ChannelOption.SO_BACKLOG, 50)
// .childOption(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addFirst("encode", new RpcEncoder(MsgBody.class))//编码器
.addFirst("decode", new RpcDecoder(MsgBody.class))//解码器
.addLast(new ChannelInboundHandlerAdapter(){
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
MsgBody body = (MsgBody) msg;
System.out.println("接收到Client端信息:" + body.toString());
//返回的数据结构
MsgBody response = new MsgBody();
response.setCode(200);
response.setData(new Date());
response.setMsg("server响应结果");
System.out.println("server thread id=" + Thread.currentThread().getId());
ctx.writeAndFlush(response);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
private void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
super.handlerRemoved(ctx);
System.out.println("有链接断开");
}
});
}
});
//启动同步监听
serverBootstrap.bind("127.0.0.1", 8081).sync().channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
workGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import top.lingkang.flychat.common.MsgBody;
import top.lingkang.flychat.common.code.RpcDecoder;
import top.lingkang.flychat.common.code.RpcEncoder;
import java.util.Date;
/**
* @author lingkang
* Created by 2022/8/12
*/
public class Test01Client {
public static void main(String[] args) throws Exception {
Bootstrap bootstrap = new Bootstrap();
EventLoopGroup group = new NioEventLoopGroup(1);
try {
bootstrap
.group(group)
.channel(MyNioSocketChannel.class)// 使用NioSocketChannel来作为连接用的channel类
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println(ch.getClass());
ch.pipeline()
.addFirst("encode", new RpcEncoder(MsgBody.class))//编码器
.addFirst("decode", new RpcDecoder(MsgBody.class))//解码器
.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
MsgBody body = (MsgBody) msg;
System.out.println("接收到Server端响应消息:" + body.toString());
// throw new RuntimeException("手动抛出");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
closeOnFlush(ctx.channel());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
private void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
});
}
});
// Start the connection attempt.
Channel channel = bootstrap.connect("127.0.0.1", 8081).sync().channel();
System.out.println("连接服务器成功");
int i = 0;
while (true) {
try {
//每2秒给服务器发一次数据
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
channel.writeAndFlush(new MsgBody(200, "客户端给服务端发消息:" + i, new Date()));
if (i == 5) {
System.out.println("通道id:" + channel.id().asLongText());
channel.close();
break;
}
}
} finally {
//关闭线程组
group.shutdownGracefully();
}
}
}
netty自定义channel id的更多相关文章
- netty 自定义协议
netty 自定义协议 netty 是什么呢? 相信很多人都被人问过这个问题.如果快速准确的回复这个问题呢?网络编程框架,netty可以让你快速和简单的开发出一个高性能的网络应用.netty是一个网络 ...
- 项目系统Netty的Channel和用户之间的关系绑定正确做法,以及Channel通道的安全性方案
前言 考虑一个功能业务,在web程序中向指定的某个用户进行实时通讯 在Web运用的Socket通讯功能中(如在线客服),为保证点对点通讯.而这个看似简单的根据用户寻到起channel通道实际会碰到不少 ...
- netty自定义解码器
在socket传输通信中容易丢包问题,什么半包问题,这些都是很正常的问题,处理方法就是定义自己的编解码规则了,让每次接收按定义好的规则为一个完整包作为数据源即可. 下面个例子就是netty自定义的一个 ...
- Netty之Channel*
Netty之Channel* 本文内容主要参考**<<Netty In Action>> ** 和Netty的文档和源码,偏笔记向. 先简略了解一下ChannelPipelin ...
- Netty 源码解析(二):Netty 的 Channel
本文首发于微信公众号[猿灯塔],转载引用请说明出处 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty源码解析(一):开始 当前:Netty 源码解析(二): Netty 的 Channel ...
- Netty自定义协议解析原理与应用
目前,大家都选择Netty做为游戏服务器框架网络通信的框架,而且目前也有很多优秀的产品是基于Netty开发的.它的稳定性,易用性和高效率性已得到广泛的认同.在游戏服务器开发中,选择netty一般就意味 ...
- spark2.1源码分析3:spark-rpc如何实现将netty的Channel隐藏在inbox中
class TransportServer bootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Overri ...
- spark-rpc是如何实现将netty的Channel隐藏在inbox中的
class TransportServer bootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Overri ...
- Netty:Channel 建立后消息发送失败
1. 问题现象 Channel 建立后消息发送失败: ChannelFuture future = DeviceManager.getBootstrap().connect(); deviceChan ...
- Netty自定义Encoder/Decoder进行对象传递
转载:http://blog.csdn.net/top_code/article/details/50901623 在上一篇文章中,我们使用Netty4本身自带的ObjectDecoder,Objec ...
随机推荐
- 在Go中如何实现并发
Go语言的并发机制是其强大和流行的一个关键特性之一.Go使用协程(goroutines)和通道(channels)来实现并发编程,这使得编写高效且可维护的并发代码变得相对容易.下面是Go的并发机制的详 ...
- 源码搭建zabbix平台
1.基于lnmp部署zabbix监控平台; zabbix优点: 1.支持自动发现服务器和网络设备: 2.分布式的监控体系和集中式的WEB管理: 3.支持主动监控和被动监控模式: 4.基于SNMP.IP ...
- 什么是yaml格式与json格式
什么是yaml格式与json格式 yaml格式:文件名格式以 .yml .yaml 为后缀,用 空格 缩进表示字段的层级关系,可读性高,易于人类管理 yaml格式 布尔值类型:只有在是true/fal ...
- Net 高级调试之三:类型元数据介绍(同步块表、类型句柄、方法描述符等)
一.简介 今天是<Net 高级调试>的第三篇文章,压力还是不小的.上一篇文章,我们浅浅的谈了谈 CLR 和 Windows 加载器是如何加载 Net 程序集的,如何找到程序的入口点的,有了 ...
- 淘天Java一面,难度适中!(上篇)
1.公司介绍 淘天集团是阿里巴巴集团全资拥有的业务集团,全球领先的科技商业公司. 淘天集团以淘宝 APP 为主要服务载体,构建国内国际供给.线上线下场景.远场近场履约相结合的商业矩阵,汇聚数十万全球和 ...
- Kubernetes:kube-apiserver 之鉴权
kubernetes:kube-apiserver 系列文章: Kubernetes:kube-apiserver 之 scheme(一) Kubernetes:kube-apiserver 之 sc ...
- Python 潮流周刊#26:requests3 的现状
你好,我是猫哥.这里每周分享优质的 Python.AI 及通用技术内容,大部分为英文.本周刊开源,欢迎投稿.另有电报频道作为副刊,补充发布更加丰富的资讯. 品牌赞助 本周刊由"Python猫 ...
- 记录jdk17相对于jdk8增加的一下主要语法糖和新特性
jdk17 发布已经好久了,作为java的长期支持版本,引入了许多有趣且实用的新特性.这些特性不仅提高了开发效率,还增强了语言的表现力和安全性.并且是SpringBoot 3.0以后版本的硬性要求,之 ...
- 如何通过 wireshark 捕获 C# 上传的图片
一:背景 1. 讲故事 这些天计划好好研究下tcp/ip,以及socket套接字,毕竟工控中设计到各种交互协议,如果只是模模糊糊的了解,对分析此类dump还是非常不利的,而研究协议最好的入手点就是用抓 ...
- 递归+记忆化递归+DP:斐波那契数列
递归:算法复杂度O(2^N) 1 int fib(int n) 2 { 3 if (n == 0) 4 { 5 return 0; 6 } 7 if (n == 1) 8 { 9 return 1; ...