电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

利用Java搭建個簡單的Netty通信實例教程

瀏覽:115日期:2022-09-01 15:08:10

前言

看過dubbo源碼的同學應該都清楚,使用dubbo協(xié)議的底層通信是使用的netty進行交互,而最近看了dubbo的Netty部分后,自己寫了個簡單的Netty通信例子。

準備

工程截圖

利用Java搭建個簡單的Netty通信實例教程

模塊詳解

rpc-common

rpc-common作為各個模塊都需使用的模塊,工程中出現(xiàn)的是一些通信時請求的參數(shù)以及返回的參數(shù),還有一些序列化的工具。

rpc-client

rpc-client中目前只是單單的一個NettyClient啟動類。

rpc-server

rpc-client中目前也只是單單的一個NettyServer服務啟動類。

需要的依賴

目前所有的依賴項都出現(xiàn)在 rpc-common 下的 pom.xml中。

<dependencies> <!-- Netty --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.10.Final</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> <!-- Protostuff --> <dependency> <groupId>com.dyuproject.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.0.9</version> </dependency> <dependency> <groupId>com.dyuproject.protostuff</groupId> <artifactId>protostuff-runtime</artifactId> <version>1.0.9</version> </dependency> <!-- Objenesis --> <dependency> <groupId>org.objenesis</groupId> <artifactId>objenesis</artifactId> <version>2.1</version> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.38</version> </dependency></dependencies>

實現(xiàn)

首先我們在common中先定義本次的Request和Response的基類對象。

public class Request { private String requestId; private Object parameter; public String getRequestId() { return requestId; } public void setRequestId(String requestId) { this.requestId = requestId; } public Object getParameter() { return parameter; } public void setParameter(Object parameter) { this.parameter = parameter; }}public class Response { private String requestId; private Object result; public String getRequestId() { return requestId; } public void setRequestId(String requestId) { this.requestId = requestId; } public Object getResult() { return result; } public void setResult(Object result) { this.result = result; }}

使用fastJson進行本次序列化

Netty對象的序列化轉換很好懂, ByteToMessageDecoder 和 MessageToByteEncoder 分別只要繼承它們,重寫方法后,獲取到Object和Byte,各自轉換就OK。

不過如果是有要用到生產(chǎn)上的同學,建議不要使用 fastJson,因為它的漏洞補丁真的是太多了,可以使用google的 protostuff。

public class RpcDecoder extends ByteToMessageDecoder { // 目標對象類型進行解碼 private Class<?> target; public RpcDecoder(Class target) { this.target = target; } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.readableBytes() < 4) { // 不夠長度丟棄 return; } in.markReaderIndex(); // 標記一下當前的readIndex的位置 int dataLength = in.readInt(); // 讀取傳送過來的消息的長度。ByteBuf 的readInt()方法會讓他的readIndex增加4 if (in.readableBytes() < dataLength) { // 讀到的消息體長度如果小于我們傳送過來的消息長度,則resetReaderIndex. 這個配合markReaderIndex使用的。把readIndex重置到mark的地方 in.resetReaderIndex(); return; } byte[] data = new byte[dataLength]; in.readBytes(data); Object obj = JSON.parseObject(data, target); // 將byte數(shù)據(jù)轉化為我們需要的對象 out.add(obj); }}public class RpcEncoder extends MessageToByteEncoder { //目標對象類型進行編碼 private Class<?> target; public RpcEncoder(Class target) { this.target = target; } @Override protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception { if (target.isInstance(msg)) { byte[] data = JSON.toJSONBytes(msg); // 使用fastJson將對象轉換為byte out.writeInt(data.length); // 先將消息長度寫入,也就是消息頭 out.writeBytes(data); // 消息體中包含我們要發(fā)送的數(shù)據(jù) } }}

NetyServer

public class NettyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { Request request = (Request) msg; System.out.println('Client Data:' + JSON.toJSONString(request)); Response response = new Response(); response.setRequestId(request.getRequestId()); response.setResult('Hello Client !'); // client接收到信息后主動關閉掉連接 ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); }}public class NettyServer { private static final Logger logger = LoggerFactory.getLogger(NettyServer.class); private String ip; private int port; public NettyServer(String ip, int port) { this.ip = ip; this.port = port; } public void server() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { final ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .option(ChannelOption.SO_SNDBUF, 32 * 1024) .option(ChannelOption.SO_RCVBUF, 32 * 1024) .option(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer<SocketChannel>() { protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new RpcDecoder(Request.class)) .addLast(new RpcEncoder(Response.class)) .addLast(new NettyServerHandler()); } }); serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); // 開啟長連接 ChannelFuture future = serverBootstrap.bind(ip, port).sync();// if (future.isSuccess()) {////new Register().register('/yanzhenyidai/com.yanzhenyidai.server', ip + ':' + port);// } future.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new NettyServer('127.0.0.1', 20000).server(); }}

關鍵名詞:

EventLoopGroup workerGroup bossGroup Server端的EventLoopGroup分為兩個,一般workerGroup作為處理請求,bossGroup作為接收請求。 ChannelOption SO_BACKLOG SO_SNDBUF SO_RCVBUF SO_KEEPALIVE 以上四個常量作為TCP連接中的屬性。 ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);

NettyServerHandler中出現(xiàn)的 ChannelFutureListener.CLOSE ,作為Server端主動關閉與Client端的通信,如果沒有主動Close,那么NettyClient將會一直處于阻塞狀態(tài),得不到NettyServer的返回信息。

NettyClient

public class NettyClient extends SimpleChannelInboundHandler<Response> { private final String ip; private final int port; private Response response; public NettyClient(String ip, int port) { this.ip = ip; this.port = port; } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, Response response) throws Exception { this.response = response; } public Response client(Request request) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { // 創(chuàng)建并初始化 Netty 客戶端 Bootstrap 對象 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group); bootstrap.channel(NioSocketChannel.class); bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new RpcDecoder(Response.class)); pipeline.addLast(new RpcEncoder(Request.class)); pipeline.addLast(NettyClient.this);} }); bootstrap.option(ChannelOption.TCP_NODELAY, true);// String[] discover = new Discover().discover('/yanzhenyidai/com.yanzhenyidai.server').split(':'); // 連接 RPC 服務器 ChannelFuture future = bootstrap.connect(ip, port).sync(); // 寫入 RPC 請求數(shù)據(jù)并關閉連接 Channel channel = future.channel(); channel.writeAndFlush(request).sync(); channel.closeFuture().sync(); return response; } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws Exception { Request request = new Request(); request.setRequestId(UUID.randomUUID().toString()); request.setParameter('Hello Server !'); System.out.println(JSON.toJSONString(new NettyClient('127.0.0.1', 30000).client(request))); }}

測試

如果以上所有內(nèi)容都準備就緒,那么就可以進行調(diào)試了。

啟動順序,先啟動NettyServer,再啟動NettyClient。

總結

記得剛出來工作時,有工作很多年的同事問我了不了解Netty,當時工作太短,直說聽過Putty,現(xiàn)在回想起來真的挺丟人的,哈哈。😋

Netty作為通信框架,如果你了解TCP,而且項目中有類似傳輸信息的需求,又不想集成HTTP或者Socket,那么Netty真的挺實用的。

參考資料:

Dubbo-Netty Netty.io

本項目Github地址:Netty-RPC

到此這篇關于利用Java搭建個簡單的Netty通信的文章就介紹到這了,更多相關Java搭建Netty通信內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持好吧啦網(wǎng)!

標簽: Java
相關文章:
主站蜘蛛池模板: 天津市能谱科技有限公司-专业的红外光谱仪_红外测油仪_紫外测油仪_红外制样附件_傅里叶红外光谱技术生产服务厂商 | 【ph计】|在线ph计|工业ph计|ph计厂家|ph计价格|酸度计生产厂家_武汉吉尔德科技有限公司 | 岛津二手液相色谱仪,岛津10A液相,安捷伦二手液相,安捷伦1100液相-杭州森尼欧科学仪器有限公司 | SOUNDWELL 编码器|电位器|旋转编码器|可调电位器|编码开关厂家-广东升威电子制品有限公司 | Type-c防水母座|贴片母座|耳机接口|Type-c插座-深圳市步步精科技有限公司 | 税筹星_灵活用工平台_企业财务顾问_财税法薪综合服务平台 | 洛阳永磁工业大吊扇研发生产-工厂通风降温解决方案提供商-中实洛阳环境科技有限公司 | NM-02立式吸污机_ZHCS-02软轴刷_二合一吸刷软轴刷-厦门地坤科技有限公司 | 深圳公司注册-工商注册代理-注册公司流程和费用_护航财税 | 合肥废气治理设备_安徽除尘设备_工业废气处理设备厂家-盈凯环保 合肥防火门窗/隔断_合肥防火卷帘门厂家_安徽耐火窗_良万消防设备有限公司 | 艺术漆十大品牌_艺术涂料加盟代理_蒙太奇艺术涂料厂家品牌|艺术漆|微水泥|硅藻泥|乳胶漆 | 轻型地埋电缆故障测试仪,频响法绕组变形测试仪,静荷式卧式拉力试验机-扬州苏电 | 百度关键词优化_网站优化_SEO价格 - 云无限好排名 | 隐形纱窗|防护纱窗|金刚网防盗纱窗|韦柏纱窗|上海青木装潢制品有限公司|纱窗国标起草单位 | 全自动贴标机-套标机-工业热风机-不干胶贴标机-上海厚冉机械 | 安徽合肥格力空调专卖店_格力中央空调_格力空调总经销公司代理-皖格制冷设备 | 附着力促进剂-尼龙处理剂-PP处理剂-金属附着力处理剂-东莞市炅盛塑胶科技有限公司 | 首页 - 军军小站|张军博客 | 400电话_400电话申请_888元包年_400电话办理服务中心_400VIP网 | 消泡剂-水处理消泡剂-涂料消泡剂-切削液消泡剂价格-东莞德丰消泡剂厂家 | 首页_欧瑞传动官方网站--主营变频器、伺服系统、新能源、软起动器、PLC、HMI | 外贸网站建设-外贸网站设计制作开发公司-外贸独立站建设【企术】 | 量子管通环-自清洗过滤器-全自动反冲洗过滤器-沼河浸过滤器 | 华禹护栏|锌钢护栏_阳台护栏_护栏厂家-华禹专注阳台护栏、楼梯栏杆、百叶窗、空调架、基坑护栏、道路护栏等锌钢护栏产品的生产销售。 | 今日扫码_溯源二维码_产品防伪一物一码_红包墙营销方案 | 塑胶跑道_学校塑胶跑道_塑胶球场_运动场材料厂家_中国塑胶跑道十大生产厂家_混合型塑胶跑道_透气型塑胶跑道-广东绿晨体育设施有限公司 | 筛分机|振动筛分机|气流筛分机|筛分机厂家-新乡市大汉振动机械有限公司 | 辽宁资质代办_辽宁建筑资质办理_辽宁建筑资质延期升级_辽宁中杭资质代办 | YJLV22铝芯铠装电缆-MYPTJ矿用高压橡套电缆-天津市电缆总厂 | 金现代信息产业股份有限公司--数字化解决方案供应商 | 工业铝型材-铝合金电机壳-铝排-气动执行器-山东永恒能源集团有限公司 | 东莞螺杆空压机_永磁变频空压机_节能空压机_空压机工厂批发_深圳螺杆空压机_广州螺杆空压机_东莞空压机_空压机批发_东莞空压机工厂批发_东莞市文颖设备科技有限公司 | 深圳天际源广告-形象堆头,企业文化墙,喷绘,门头招牌设计制作专家 | 佛山市钱丰金属不锈钢蜂窝板定制厂家|不锈钢装饰线条|不锈钢屏风| 电梯装饰板|不锈钢蜂窝板不锈钢工艺板材厂家佛山市钱丰金属制品有限公司 | bkzzy在职研究生网 - 在职研究生招生信息咨询平台 | 冷油器-冷油器换管改造-连云港灵动列管式冷油器生产厂家 | 【MBA备考网】-2024年工商管理硕士MBA院校/报考条件/培训/考试科目/提前面试/考试/学费-MBA备考网 | 分类168信息网 - 分类信息网 免费发布与查询 | 蜘蛛车-登高车-高空作业平台-高空作业车-曲臂剪叉式升降机租赁-重庆海克斯公司 | 环氧树脂地坪漆_济宁市新天地漆业有限公司 | 聚合氯化铝价格_聚合氯化铝厂家_pac絮凝剂-唐达净水官网 |