Netty4.x中文教程系列(七)UDP协议
将近快一年时间没有更新Netty的博客。一方面原因是因为项目进度的问题。另外一方面是博主有一段时间去熟悉Unity3D引擎。
本章节主要记录博主自己Netty的UDP协议使用。
1. 构建UDP服务端
首先我们应该清楚UDP协议是一种无连接状态的协议。所以Netty框架区别于一般的有链接协议服务端启动程序(ServerBootstrap)。
Netty开发基于UDP协议的服务端需要使用Bootstrap
package dev.tinyz.game; 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.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.MessageToMessageDecoder; import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.List; /**
* @author TinyZ on 2015/6/8.
*/
public class GameMain { public static void main(String[] args) throws InterruptedException { final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap();
bootstrap.channel(NioDatagramChannel.class);
bootstrap.group(nioEventLoopGroup);
bootstrap.handler(new ChannelInitializer<NioDatagramChannel>() { @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
} @Override
protected void initChannel(NioDatagramChannel ch) throws Exception {
ChannelPipeline cp = ch.pipeline();
cp.addLast("framer", new MessageToMessageDecoder<DatagramPacket>() {
@Override
protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List<Object> out) throws Exception {
out.add(msg.content().toString(Charset.forName("UTF-8")));
}
}).addLast("handler", new UdpHandler());
}
});
// 监听端口
ChannelFuture sync = bootstrap.bind(9009).sync();
Channel udpChannel = sync.channel(); // String data = "我是大好人啊";
// udpChannel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(data.getBytes(Charset.forName("UTF-8"))), new InetSocketAddress("192.168.2.29", 9008))); Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
nioEventLoopGroup.shutdownGracefully();
}
}));
}
}
于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端口。代码如下:
package dev.tinyz.game; 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.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.MessageToMessageDecoder; import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.List; /**
* @author TinyZ on 2015/6/8.
*/
public class GameMain { public static void main(String[] args) throws InterruptedException { final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap();
bootstrap.channel(NioDatagramChannel.class);
bootstrap.group(nioEventLoopGroup);
bootstrap.handler(new ChannelInitializer<NioDatagramChannel>() { @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
} @Override
protected void initChannel(NioDatagramChannel ch) throws Exception {
ChannelPipeline cp = ch.pipeline();
cp.addLast("framer", new MessageToMessageDecoder<DatagramPacket>() {
@Override
protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List<Object> out) throws Exception {
out.add(msg.content().toString(Charset.forName("UTF-8")));
}
}).addLast("handler", new UdpHandler());
}
});
// 监听端口
ChannelFuture sync = bootstrap.bind(0).sync();
Channel udpChannel = sync.channel(); String data = "我是大好人啊";
udpChannel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(data.getBytes(Charset.forName("UTF-8"))), new InetSocketAddress("192.168.2.29", 9008))); Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
nioEventLoopGroup.shutdownGracefully();
}
}));
}
}
和上面的“服务端”代码最大的差别就是,监听的端口号修改成0.为
使用Netty的Channel发送DatagramPacket。写好目标地址,然后运行起来就可以自己测试一下了。
3. JAVA原生UDP
有朋友这个时候就会问:为什么不是有JAVA原生的UDP呢?
其实很简单。说白了Netty使用的也是Java底层的代码。只是做了一层封装,以便于使用。服务端使用Netty框架构建高性能,高扩展的UDP服务器。
客户端则使用JAVA或者任意其他的语言的API(遵循UDP协议即可)。
下面上一段博主使用的的JAVA
package dev.tinyz.game; import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.Charset; /**
* @author TinyZ on 2015/6/10.
*/
public class UdpTest { public static void main(String[] args) throws IOException {
final String data = "博主邮箱:zou90512@126.com";
byte[] bytes = data.getBytes(Charset.forName("UTF-8"));
InetSocketAddress targetHost = new InetSocketAddress("192.168.2.29", 9009); // 发送udp内容
DatagramSocket socket = new DatagramSocket();
socket.send(new DatagramPacket(bytes, 0, bytes.length, targetHost));
}
}
..
ps.UDP协议最大特点就是效率高,速度快。用于某些场合可以极大改善系统的性能。
博主在这里引入这个Netty实现UDP的服务端,主要目的。嘻嘻。就是想开源拙作:eyeOfSauron日志系统。
Netty4.x中文教程系列(七)UDP协议的更多相关文章
- Netty4.x中文教程系列(一) 目录及概述
Netty4.x中文教程系列(一)目录及概述 Netty 提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. Netty是一个NIO客户端 服务端框架 ...
- Netty4.x中文教程系列(五)编解码器Codec
Netty4.x中文教程系列(五)编解码器Codec 上一篇文章详细解释了ChannelHandler的相关构架设计,版本和设计逻辑变更等等. 这篇文章主要在于讲述Handler里面的Codec,也就 ...
- Netty4.x中文教程系列(四) 对象传输
Netty4.x中文教程系列(四) 对象传输 我们在使用netty的过程中肯定会遇到传输对象的情况,Netty4通过ObjectEncoder和ObjectDecoder来支持. 首先我们定义一个U ...
- Netty4.x中文教程系列(三) ChannelHandler
Netty4.x中文教程系列(四) ChannelHandler 上一篇文章详细解释了Hello World示例的代码.里面涉及了一些Netty框架的基础. 这篇文章用以解释ChannelHandl ...
- Netty4.x中文教程系列(六) 从头开始Bootstrap
Netty4.x中文教程系列(六) 从头开始Bootstrap 其实自从中文教程系列(五)一直不知道自己到底想些什么.加上忙着工作上出现了一些问题.本来想就这么放弃维护了.没想到有朋友和我说百度搜索推 ...
- struts2官方 中文教程 系列七:消息资源文件
介绍 在本教程中,我们将探索使用Struts 2消息资源功能(也称为 resource bundles 资源绑定).消息资源提供了一种简单的方法,可以将文本放在一个视图页面中,通过应用程序,创建表单字 ...
- Netty4.x中文教程系列(二) Hello World !
在中国程序界.我们都是学着Hello World !慢慢成长起来的.逐渐从一无所知到熟悉精通的. 第二章就从Hello World 开始讲述Netty的中文教程. 首先创建一个Java项目.引入一个N ...
- Netty4.x中文教程系列(二) Hello World !<转>
在中国程序界.我们都是学着Hello World !慢慢成长起来的.逐渐从一无所知到熟悉精通的. 第二章就从Hello World 开始讲述Netty的中文教程. 首先创建一个Java项目.引入一个N ...
- Netty4.x中文教程系列(三) Hello World !详解
Netty 中文教程 (二) Hello World !详解 上一篇文章,笔者提供了一个Hello World 的Netty示例. 时间过去了这么久,准备解释一下示例代码. 1.HelloServer ...
随机推荐
- Mysql触发器、模糊查找、存储过程、内置函数
原本觉得Mysql的一些知识还是差不多了,但是在实际上在项目上用的时候,发现什么都忘记了.现在重新回顾一下,顺便做个笔记. 触发器 ...
- Android -- 启动模式
Android的启动模式分为四种: standard 模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中. singleTop 如果在任务的栈顶正好存在该Activity ...
- Virtualbox中Linux添加新磁盘并创建分区
原文:https://www.linuxidc.com/Linux/2017-01/139616.htm ----------------------------------------------- ...
- Sqlserver DateTime转换成SMALLDATETIME时“产生一个超出范围的值”
工作中遇到一个问题,A表中字段(DateTime1)的数据类型为DateTime,新建了一张表B的SMALLDATETIME1字段的数据来自A表的DateTime1 但在将A表字段DateTime1导 ...
- 学生表 课程表 成绩表 教师表 50个常用sql语句
原文:http://www.cnblogs.com/zengxiangzhan/archive/2009/09/23/1572276.html Student(S#,Sname,Sage,Ssex) ...
- (剑指Offer)面试题9:斐波那契数列
题目: 现在要求输入一个整数n,请你输出斐波那契数列的第n项. 斐波那契数列的定义: f(0)=0;f(1)=1; f(n)=f(n-1)+f(n-2) 思路: 1.递归: 根据递推公式来实现 优点: ...
- Android小技术知识(多用于面试)
Android Dev Doc Android 开发 多使用内部类 使用方便且效率高 UI方面的知识 一.在编写layout的xml文件时,一定要仔细!如果在报错的时候,如何解决? 解决:将xml仔细 ...
- 稍复杂的ionic例子:显示一个列表,并且允许点击进入列表项
这个例子,按照MVC的方式进行了分层,下面是代码: demo3.htm <!DOCTYPE html> <html ng-app="app"> <he ...
- PHP RESTful
PHP RESTful REST(英文:Representational State Transfer,简称REST) ,指的是一组架构约束条件和原则. 符合REST设计风格的Web API称为RES ...
- 算法笔记_146:TarJan算法的应用(Java)
目录 1 问题描述 2 解决方案 1 问题描述 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M& ...