• Netty4.x中文教程系列(七)UDP协议


             

      将近快一年时间没有更新Netty的博客。一方面原因是因为项目进度的问题。另外一方面是博主有一段时间去熟悉Unity3D引擎。

      本章节主要记录博主自己Netty的UDP协议使用。

      1.  构建UDP服务端

      首先我们应该清楚UDP协议是一种无连接状态的协议。所以Netty框架区别于一般的有链接协议服务端启动程序(ServerBootstrap)。

      Netty开发基于UDP协议的服务端需要使用Bootstrap

      

     1 package dev.tinyz.game;
     2 
     3 import io.netty.bootstrap.Bootstrap;
     4 import io.netty.buffer.Unpooled;
     5 import io.netty.channel.*;
     6 import io.netty.channel.nio.NioEventLoopGroup;
     7 import io.netty.channel.socket.DatagramPacket;
     8 import io.netty.channel.socket.nio.NioDatagramChannel;
     9 import io.netty.handler.codec.MessageToMessageDecoder;
    10 
    11 import java.net.InetSocketAddress;
    12 import java.nio.charset.Charset;
    13 import java.util.List;
    14 
    15 /**
    16  * @author TinyZ on 2015/6/8.
    17  */
    18 public class GameMain {
    19 
    20     public static void main(String[] args) throws InterruptedException {
    21 
    22         final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
    23 
    24         Bootstrap bootstrap = new Bootstrap();
    25         bootstrap.channel(NioDatagramChannel.class);
    26         bootstrap.group(nioEventLoopGroup);
    27         bootstrap.handler(new ChannelInitializer<NioDatagramChannel>() {
    28 
    29             @Override
    30             public void channelActive(ChannelHandlerContext ctx) throws Exception {
    31                 super.channelActive(ctx);
    32             }
    33 
    34             @Override
    35             protected void initChannel(NioDatagramChannel ch) throws Exception {
    36                 ChannelPipeline cp = ch.pipeline();
    37                 cp.addLast("framer", new MessageToMessageDecoder<DatagramPacket>() {
    38                     @Override
    39                     protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List<Object> out) throws Exception {
    40                         out.add(msg.content().toString(Charset.forName("UTF-8")));
    41                     }
    42                 }).addLast("handler", new UdpHandler());
    43             }
    44         });
    45         // 监听端口
    46         ChannelFuture sync = bootstrap.bind(9009).sync();
    47         Channel udpChannel = sync.channel();
    48 
    49 //        String data = "我是大好人啊";
    50 //        udpChannel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(data.getBytes(Charset.forName("UTF-8"))), new InetSocketAddress("192.168.2.29", 9008)));
    51 
    52         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    53             @Override
    54             public void run() {
    55                 nioEventLoopGroup.shutdownGracefully();
    56             }
    57         }));
    58     }
    59 }
    View Code

      于Tcp协议的客户端启动程序基本一样。唯一区别就在于,UDP服务器使用的是bind方法,来监听端口

      在Netty的Bootstrap类中的注释,发现有如下注释内容:

      

      大意就是:bind()用于UDP, TCP连接使用connect()。

      上面的源码监听的是端口9009,那么所有使用UDP协议的数据,发送到端口9009,就会被我们的Netty接收到了。

      为了输出方便,博主在上面的代码中增加一个MessageToMessageDecoder将接收到的Datagram,排除其他信息,仅将字符串传递下去。并在UDPHandler中打印出来。

      2.  构建UDP客户端

      UDP协议来说,其实没有客户端和服务端的区别啦。只是为了贴近TCP协议做的一点文字描述上面的区分。

      简单来讲,上面的那段逻辑其实就可以作为UDP客户端来使用。注释掉的那行逻辑其实就是发送“我是大好人啊”这个字符串到ip地址为192.168.2.29的服务端的9008端口。代码如下:

      

     1 package dev.tinyz.game;
     2 
     3 import io.netty.bootstrap.Bootstrap;
     4 import io.netty.buffer.Unpooled;
     5 import io.netty.channel.*;
     6 import io.netty.channel.nio.NioEventLoopGroup;
     7 import io.netty.channel.socket.DatagramPacket;
     8 import io.netty.channel.socket.nio.NioDatagramChannel;
     9 import io.netty.handler.codec.MessageToMessageDecoder;
    10 
    11 import java.net.InetSocketAddress;
    12 import java.nio.charset.Charset;
    13 import java.util.List;
    14 
    15 /**
    16  * @author TinyZ on 2015/6/8.
    17  */
    18 public class GameMain {
    19 
    20     public static void main(String[] args) throws InterruptedException {
    21 
    22         final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
    23 
    24         Bootstrap bootstrap = new Bootstrap();
    25         bootstrap.channel(NioDatagramChannel.class);
    26         bootstrap.group(nioEventLoopGroup);
    27         bootstrap.handler(new ChannelInitializer<NioDatagramChannel>() {
    28 
    29             @Override
    30             public void channelActive(ChannelHandlerContext ctx) throws Exception {
    31                 super.channelActive(ctx);
    32             }
    33 
    34             @Override
    35             protected void initChannel(NioDatagramChannel ch) throws Exception {
    36                 ChannelPipeline cp = ch.pipeline();
    37                 cp.addLast("framer", new MessageToMessageDecoder<DatagramPacket>() {
    38                     @Override
    39                     protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List<Object> out) throws Exception {
    40                         out.add(msg.content().toString(Charset.forName("UTF-8")));
    41                     }
    42                 }).addLast("handler", new UdpHandler());
    43             }
    44         });
    45         // 监听端口
    46         ChannelFuture sync = bootstrap.bind(0).sync();
    47         Channel udpChannel = sync.channel();
    48 
    49         String data = "我是大好人啊";
    50         udpChannel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(data.getBytes(Charset.forName("UTF-8"))), new InetSocketAddress("192.168.2.29", 9008)));
    51 
    52         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    53             @Override
    54             public void run() {
    55                 nioEventLoopGroup.shutdownGracefully();
    56             }
    57         }));
    58     }
    59 }
    View Code

      和上面的“服务端”代码最大的差别就是,监听的端口号修改成0.

      使用Netty的Channel发送DatagramPacket。写好目标地址,然后运行起来就可以自己测试一下了。

      3.  JAVA原生UDP

      有朋友这个时候就会问:为什么不是有JAVA原生的UDP呢?

      其实很简单。说白了Netty使用的也是Java底层的代码。只是做了一层封装,以便于使用。服务端使用Netty框架构建高性能,高扩展的UDP服务器。

      客户端则使用JAVA或者任意其他的语言的API(遵循UDP协议即可)。

      下面上一段博主使用的的JAVA

      

     1 package dev.tinyz.game;
     2 
     3 import java.io.IOException;
     4 import java.net.DatagramPacket;
     5 import java.net.DatagramSocket;
     6 import java.net.InetSocketAddress;
     7 import java.nio.charset.Charset;
     8 
     9 /**
    10  * @author TinyZ on 2015/6/10.
    11  */
    12 public class UdpTest {
    13 
    14     public static void main(String[] args) throws IOException {
    15         final String data = "博主邮箱:zou90512@126.com";
    16         byte[] bytes = data.getBytes(Charset.forName("UTF-8"));
    17         InetSocketAddress targetHost = new InetSocketAddress("192.168.2.29", 9009);
    18 
    19         // 发送udp内容
    20         DatagramSocket socket = new DatagramSocket();
    21         socket.send(new DatagramPacket(bytes, 0, bytes.length, targetHost));
    22     }
    23 }
    View Code

      ..

      ps.UDP协议最大特点就是效率高,速度快。用于某些场合可以极大改善系统的性能。

      博主在这里引入这个Netty实现UDP的服务端,主要目的。嘻嘻。就是想开源拙作:eyeOfSauron日志系统。

  • 相关阅读:
    邮票面值设计(codevs 1047) 题解
    练习 : 生成器和模块
    练习 : 数据类型之字符串
    练习 : 函数基础
    练习 : 高阶函数
    练习 : 数据类型之列表
    练习 : 数据类型之元组
    练习 : 数据类型之字典
    练习 : 分支结构和循环结构
    练习 : 变量和运算符
  • 原文地址:https://www.cnblogs.com/zou90512/p/4567287.html
Copyright © 2020-2023  润新知