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 ...
随机推荐
- 解决Oracle监听错误的一种办法
1:事出有因 安装oracle数据库,默认安装的是orcl数据库,安装完成后查看了一下字符集是gbk的,由于业务需要al32utf8的字符集,所以需要修改字符集,但是修改却无效.于是就删除了默认的or ...
- phpsso 与 Discuz!
经过测试仍然有问题,phpcms登陆,论坛可以实现同步登陆,但论坛登陆phpcms无法同步登陆.但总体来说也能使用了.如果有更好的方法欢迎补充. 整合原理: UCenter 作服务端:phpsso 与 ...
- 【python】列出http://www.cnblogs.com/xiandedanteng/p/中的标题
# 列出http://www.cnblogs.com/xiandedanteng/p/中的标题 from bs4 import BeautifulSoup import requests user_a ...
- (C++)虚函数表解析(转)
(文章出处不详,转自:http://blog.csdn.net/hairetz/article/details/4137000) C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用 ...
- 查找文件工具find
与locate.whereis命令相比,find具有本质的区别: 首先,find是从指定的位置进行遍历查找(可以理解为对文件和目录进行逐一查找). 其次,find可以查找具有某一类特征的文件(例如查找 ...
- JUnit单元测试基础要点
JUnit单元测试基础要点 1.JUnit是一种测试代码的框架,测试的目的是:保证代码没错,而不是保证代码正确. 2.测试类一般不要和目标类放在一起,但编译成的class文件是放在一起的. 3.单元测 ...
- HBase源代码分析之HRegionServer上MemStore的flush处理流程(一)
在<HBase源代码分析之HRegion上MemStore的flsuh流程(一)>.<HBase源代码分析之HRegion上MemStore的flsuh流程(二)>等文中.我们 ...
- Android开发之定位系统
2013-07-04 定位系统 全球定位系统(Global Positioning System, GPS), 又称全球卫星定位系统. 最少只需其中3颗卫星,就能迅速确定用户组地球所处的位置及海拔高度 ...
- MySQL实现允许远程用户登录(使用Navicat for MySQL工具)
一.方式一和方式二都可以,建议方式二. 前提条件:在服务器上将MySQL的配置文件 /etc/mysql/my.cnf中使用: sudo vi /etc/mysql/my.cnf 找到bind-add ...
- C#调取java接口
1. public class APIRequest { //public static string commonUrl = @"http://192.168.2.186 ...