netty实现udp编程示例

    netty实现udp编程比普通的java原生api实现udp编程要稍微复杂一些,但是一旦实现了,也很简单,而且我们不用关心socket这部分,我们只需要关注我们的业务代码即可。

    这里给出一个模拟udp server与client的示例,看代码部分,两者很像,但是也有区别,server主要偏向bind并且监听端口,等待客户端连接。而client偏向向server发送数据并接收返回的数据。

    无论是server,还是client,他们的主要收发数据逻辑会在各自handler中体现。

    udp客户端,不像tcp客户端那样,需要明确指定建立socket连接,即非必须存在connect这一步,只是在发送的packet中指定发送的目的host与port,这也符合udp协议的特点,是一种非可靠的传输协议。

    UDPServerApp.java

package com.xxx.udpnetty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;

public class UDPServerApp {
	public static void main(String[] args) {
		Bootstrap bootstrap = new Bootstrap();
		EventLoopGroup workGroup = new NioEventLoopGroup();
		bootstrap.group(workGroup).channel(NioDatagramChannel.class)
		.option(ChannelOption.SO_BROADCAST, true)
		.handler(new ChannelInitializer<NioDatagramChannel>() {

			@Override
			protected void initChannel(NioDatagramChannel ch) throws Exception {
				// TODO Auto-generated method stub
				ch.pipeline().addLast(new UDPServerHandler());
			}
		});
		try {
			Channel channel = bootstrap.bind("192.168.0.107", 8080).sync().channel();
			channel.closeFuture().sync().await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

    UDPServerHandler.java

package com.xxx.udpnetty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;

public class UDPServerHandler extends SimpleChannelInboundHandler<DatagramPacket>{

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
			throws Exception {
		ByteBuf buf = msg.content();
		int len = buf.readableBytes();
		byte[] data = new byte[len];
		buf.readBytes(data);
		String receive = new String(data,"UTF-8");
		System.out.println(receive);
		ctx.writeAndFlush(new DatagramPacket(Unpooled.wrappedBuffer("hello,netty".getBytes()), msg.sender()));
	}

}

    UDPClientApp.java

package com.xxx.udpnetty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;

public class UDPClientApp {
	public static void main(String[] args) {
		Bootstrap bootstrap = new Bootstrap();
		EventLoopGroup workGroup = new NioEventLoopGroup();
		bootstrap.group(workGroup).channel(NioDatagramChannel.class)
		.option(ChannelOption.SO_BROADCAST, true)
		.handler(new ChannelInitializer<NioDatagramChannel>() {

			@Override
			protected void initChannel(NioDatagramChannel ch) throws Exception {
				// TODO Auto-generated method stub
				ch.pipeline().addLast(new UDPClientHandler());
			}
		});
		try {
			Channel channel = bootstrap.bind(0).sync().channel();
			channel.closeFuture().sync().await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

    UDPClientHandler.java

package com.xxx.udpnetty;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;

public class UDPClientHandler extends SimpleChannelInboundHandler<DatagramPacket>{

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
			throws Exception {
		ByteBuf buf = msg.content();
		int len = buf.readableBytes();
		byte[] data = new byte[len];
		buf.readBytes(data);
		String receive = new String(data,"UTF-8");
		System.out.println("client->"+receive);
	}
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("hello,server",Charset.forName("UTF-8")),
				new InetSocketAddress("192.168.0.107", 8080)));
	}

}

    这里我们需要先启动UDPServerApp.java,然后启动UDPClientApp.java

    这时候,控制台会分别打印hello,server  、  client->hello,netty。 

    无论是java原生api实现的udp,还是netty实现的udp,都是需要有一个server监听一个端口,等待连接;客户端启动通过发送一个请求send(datagrampacket)建立连接,而不是类似tcp那样connect(host,port)来建立连接,服务端会根据收到的请求来发送一个回复给客户端,因为这时候服务端才知道客户端连接的ip和端口,才能通过ip和端口给客户端发送回复,否则,服务端不知道要向谁发送回复数据。

    我们仔细观察会发现UDPServerApp.java和UDPClientApp.java代码几乎一模一样,不同的只有两句,分别是设置handler,和bind这里。

    1 、 ch.pipeline().addLast(new UDPServerHandler());

            ch.pipeline().addLast(new UDPClientHandler());

    2 、 Channel channel = bootstrap.bind("192.168.0.107", 8080).sync().channel();  //bind是为了监听

            Channel channel = bootstrap.bind(0).sync().channel();     //bind是为了建立datagramsocket,这个端口可以随便定义,只要不与8080重复即可。

    这里不管是server,还是client发送数据,都是datagrampacket,而且都需要指定host,port,只有这样才能发送给目标,否则就是没有目的的发送,不会被程序所接收。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章