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,只有這樣才能發送給目標,否則就是沒有目的的發送,不會被程序所接收。

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