23 网络编程 Netty框架 初识

1.1 Netty简介

Netty是最流行的NIO框架,他的健壮性、功能、性能、可定制性和可扩展性在同类框架都是首屈一指的。它已经得到成百上千的上也项目验证,如HadoopRPC框架Avro、以及JMS框架,强大的RocketMQ,还有主流的分布式通信框架Dubbox等等。主要原因:简单。

Netty是基于Java NIO的网络应用框架

 

1.2 Netty架构组成

 

1.3 Netty特性

 

2.1  Netty初识

下载Netty包:http://netty.io/

Netty实现通信的步骤:

1、创建两个的NIO线程组,一个专门用于网络事件处理(接受客户端的连接),另一个则进行网络通信读写。

2、创建一个ServerBootstrap对象,配置Netty的一系列参数,例如接收传出数据的缓存大小等等。

3、创建一个实际处理数据的类ChannelInitializer,进行初始化的准备工作,例如设置接收传出数据的字符集、格式、已经实际处理数据的接口。

4、绑定端口,执行同步阻塞方法等待服务端启动即可。

解读netty示例:http://ifeve.com/netty5-user-guide/


代码示例:Server


package edu.sdut.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
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.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
 * Server端
 * @author Vision_TXG
 *
 */
public class Server {
	public static void main(String[] args) throws Exception {
		
		//1、第一个线程组是用于接收Client端的接收的
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		//2、第二个线程组是用于实际的的业务处理操作的
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		
		//3、创建一个辅助类,对Server端进行一系列的配置
		ServerBootstrap b = new ServerBootstrap();
		//将两个线程组加入进来
		b.group(bossGroup,workerGroup)
		//执行使用NioServerSocketChannel类型的通道
		.channel(NioServerSocketChannel.class)
		//一定要使用childHandler去保定具体的事件处理器
		.childHandler(new ChannelInitializer<SocketChannel>() {

			@Override
			protected void initChannel(SocketChannel sc) throws Exception {
				sc.pipeline().addLast(new ServerHandler());
			}
			
		})
		.option(ChannelOption.SO_BACKLOG,128)
		.option(ChannelOption.SO_SNDBUF, 32*1024)   //设置发送缓冲大小
		.option(ChannelOption.SO_RCVBUF, 32*1024)   //设置接收缓冲大小
		//保持连接
		.childOption(ChannelOption.SO_KEEPALIVE, true);
		
		//绑定指定的端口进行监听,可以绑定多个端口
		ChannelFuture f = b.bind(8765).sync(); //异步的方法
		
		//相当于一个阻塞的一个作用,不能让主程序停止
		f.channel().closeFuture().sync();
		workerGroup.shutdownGracefully();
		bossGroup.shutdownGracefully();
		
	}
}

ServerHandler类:

package edu.sdut.netty;

import java.util.Scanner;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

public class ServerHandler extends ChannelHandlerAdapter{

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		//((ByteBuf) msg).release();
		try {
			//do somoeting msg
			ByteBuf buf = (ByteBuf)msg;
			
			//根据buf中的数据大小初始化byte
			byte[] data = new byte[buf.readableBytes()];
			//将buf中的数据读到byte中
			buf.readBytes(data);
			String request = new String(data,"gbk");
			System.out.println("Server : " + request);
			
			//发给客户端
			String response = "I'm Server";
			Scanner cin = new Scanner(System.in);
			System.out.println("Server回: ");
			response = cin.nextLine();
			
			
			//在写的同时是有返回对象的,返回的Future类型的
			ChannelFuture cf = ctx.write(Unpooled.copiedBuffer(response.getBytes()));
			//只要数据发送完之后,就回主动断开连接,实现长连接和短连接
			cf.addListener(ChannelFutureListener.CLOSE);
			
			ctx.flush();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			
			//读数据的时候需要释放,如果胡需要读数据就不用释放
			//用完释放
			ReferenceCountUtil.release(msg);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		ctx.close();
	}

}

Client端:

package edu.sdut.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
 * Client端
 * @author Vision_TXG
 *
 */
public class Client {

	public static void main(String[] args) throws Exception {
		
		EventLoopGroup group = new NioEventLoopGroup();
		Bootstrap b = new Bootstrap();
		b.group(group)
		.channel(NioSocketChannel.class)
		.handler(new ChannelInitializer<SocketChannel>() {

			@Override
			protected void initChannel(SocketChannel sc) throws Exception {
				
				sc.pipeline().addLast(new ClientHandler());
			}
			
		});
		//非阻塞的异步通道
		ChannelFuture cf1 = b.connect("127.0.0.1",8765).sync();
		
		//Unpooled.copiedBuffer("I'm String".getBytes())的作用是将字符串转换为字节数组
		
		//客户端进行写数据
		cf1.channel().write(Unpooled.copiedBuffer("I'm String".getBytes()));
		cf1.channel().flush();
		
		cf1.channel().closeFuture().sync();
		group.shutdownGracefully();
	}
}

ClientHandler类:

package edu.sdut.netty;

import java.util.Scanner;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

public class ClientHandler extends ChannelHandlerAdapter{

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		//((ByteBuf) msg).release();
		
		try {
			//do somoeting msg
			ByteBuf buf = (ByteBuf)msg;
			
			//根据buf中的数据大小初始化byte
			byte[] data = new byte[buf.readableBytes()];
			//将buf中的数据读到byte中
			buf.readBytes(data);
			String response = new String(data,"gbk");
			System.out.println("Client : " + response);
			
			
			//发给服务器
			String res = "I'm Client";
			Scanner cin = new Scanner(System.in);
			System.out.println("Client回: ");
			res = cin.nextLine();
			ctx.write(Unpooled.copiedBuffer(res.getBytes()));
			ctx.flush();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//用完释放
			ReferenceCountUtil.release(msg);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		ctx.close();
	}
	
}






猜你喜欢

转载自blog.csdn.net/txgANG/article/details/80958700