小傅哥 | https://bugstack.cn 沉淀、分享、成長,讓自己和他人都能有所收獲。專注于原創專題案例編寫,目前已完成的專題有;Netty4.x實戰專題案例、用Java實現JVM、基于JavaAgent的全鏈路監控、手寫RPC框架、架構設計專題案例、源碼分析等。你用劍 、我用刀 ,好的代碼都很燒,望你不吝出招!
一、前言介紹
在Netty通信中UDP的實現方式也非常簡單,只要注意部分代碼區別于TCP即可。本章節需要注意的知識點 ;NioDatagramChannel、ChannelOption.SO_BROADCAST
Internet 協議集支持一個無連接的傳輸協議,該協議稱為用戶數據報協議(UDP,User Datagram Protocol)。UDP 為應用程序提供了一種無需建立連接就可以發送封裝的 IP 數據報的方法。RFC 768 1 描述了 UDP。
Internet 的傳輸層有兩個主要協議,互為補充。無連接的是 UDP,它除了給應用程序發送數據包功能并允許它們在所需的層次上架構自己的協議之外,幾乎沒有做什么特別的的事情。面向連接的是 TCP,該協議幾乎做了所有的事情。
二、環境準備
1、jdk1.8【jdk1.7以下只能部分支持netty】
2、Netty4.1.36.Final【netty3.x 4.x 5每次的變化較大,接口類名也隨著變化】
3、NetAssist 網絡調試助手,可以從網上下載也可以聯系我,微信公眾號:bugstack蟲洞棧 | 關注回復你的郵箱
三、代碼示例
itstack-demo-netty-1-11
└── src├── main│ └── java│ └── org.itstack.demo.netty│ ├── client│ │ ├── MyChannelInitializer.java│ │ ├── MyClientHandler.java│ │ └── NettyClient.java│ └── server│ ├── MyChannelInitializer.java│ ├── MyServerHandler.java│ └── NettyServer.java└── test└── java└── org.itstack.demo.netty.test└── ApiTest.java
client/MyChannelInitializer.java
/*** 蟲洞棧:https://bugstack.cn* 公眾號:bugstack蟲洞棧 {獲取學習源碼}* 蟲洞群:①群5398358 ②群5360692* Create by fuzhengwei on @2019*/
public class MyChannelInitializer extends ChannelInitializer<NioDatagramChannel> {@Overrideprotected void initChannel(NioDatagramChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 解碼轉String,注意調整自己的編碼格式GBK、UTF-8//pipeline.addLast("stringDecoder", new StringDecoder(Charset.forName("GBK")));pipeline.addLast(new MyClientHandler());}}
client/MyClientHandler.java
/*** 蟲洞棧:https://bugstack.cn* 公眾號:bugstack蟲洞棧 {獲取學習源碼}* 蟲洞群:①群5398358 ②群5360692* Create by fuzhengwei on @2019*/
public class MyClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {//接受服務端發送的內容@Overrideprotected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {String msg = packet.content().toString(Charset.forName("GBK"));System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " UDP客戶端接收到消息:" + msg);}}
client/NettyClient.java
/*** 蟲洞棧:https://bugstack.cn* 公眾號:bugstack蟲洞棧 {獲取學習源碼}* 蟲洞群:①群5398358 ②群5360692* Create by fuzhengwei on @2019*/
public class NettyClient {public static void main(String[] args) {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioDatagramChannel.class).handler(new MyChannelInitializer());Channel ch = b.bind(7398).sync().channel();//向目標端口發送信息ch.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("你好端口7397的bugstack蟲洞棧,我是客戶端小愛,你在嗎!", Charset.forName("GBK")),new InetSocketAddress("127.0.0.1", 7397))).sync();ch.closeFuture().await();} catch (Exception e) {e.printStackTrace();} finally {group.shutdownGracefully();}}}
server/MyChannelInitializer.java
/*** 蟲洞棧:https://bugstack.cn* 公眾號:bugstack蟲洞棧 {獲取學習源碼}* 蟲洞群:①群5398358 ②群5360692* Create by fuzhengwei on @2019*/
public class MyChannelInitializer extends ChannelInitializer<NioDatagramChannel> {private EventLoopGroup group = new NioEventLoopGroup();@Overrideprotected void initChannel(NioDatagramChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 解碼轉String,注意調整自己的編碼格式GBK、UTF-8//pipeline.addLast("stringDecoder", new StringDecoder(Charset.forName("GBK")));pipeline.addLast(group, new MyServerHandler());}}
server/MyServerHandler.java
/*** 蟲洞棧:https://bugstack.cn* 公眾號:bugstack蟲洞棧 {獲取學習源碼}* 蟲洞群:①群5398358 ②群5360692* Create by fuzhengwei on @2019*/
public class MyServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {String msg = packet.content().toString(Charset.forName("GBK"));System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " UDP服務端接收到消息:" + msg);//向客戶端發送消息String json = "微信公眾號:bugstack蟲洞棧,通知:我已經收到你的消息rn";// 由于數據報的數據是以字符數組傳的形式存儲的,所以傳轉數據byte[] bytes = json.getBytes(Charset.forName("GBK"));DatagramPacket data = new DatagramPacket(Unpooled.copiedBuffer(bytes), packet.sender());ctx.writeAndFlush(data);//向客戶端發送消息}}
server/NettyServer.java
/*** 蟲洞棧:https://bugstack.cn* 公眾號:bugstack蟲洞棧 {獲取學習源碼}* 蟲洞群:①群5398358 ②群5360692* Create by fuzhengwei on @2019*/
public class NettyServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST, true) //廣播.option(ChannelOption.SO_RCVBUF, 2048 * 1024)// 設置UDP讀緩沖區為2M.option(ChannelOption.SO_SNDBUF, 1024 * 1024)// 設置UDP寫緩沖區為1M.handler(new MyChannelInitializer());ChannelFuture f = b.bind(7397).sync();System.out.println("itstack-demo-netty udp server start done. {關注公眾號:bugstack蟲洞棧,獲取源碼}");f.channel().closeFuture().sync();} finally {//優雅的關閉釋放內存group.shutdownGracefully();}}}
四、測試結果
啟動NettyServer
itstack-demo-netty udp server start done. {關注公眾號:bugstack蟲洞棧,獲取源碼}
2019-09-01 16:58:34 UDP服務端接收到消息:你好端口7397的bugstack蟲洞棧,我是客戶端小愛,你在嗎!
2019-09-01 16:59:15 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:15 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:16 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:17 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:17 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:18 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:18 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:19 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!
2019-09-01 16:59:19 UDP服務端接收到消息:你好,有人在關注bugstack公眾號,關注可以獲得源碼!Process finished with exit code -1
啟動NettyClient
2019-09-01 16:58:34 UDP客戶端接收到消息:微信公眾號:bugstack蟲洞棧,通知:我已經收到你的消息Process finished with exit code -1
在啟動一個網絡調試助手,NetAssist | 這樣方便我們驗證
