网络编程 netty

       Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。

client--server交互demo

server:

       在server中定义线程组、配置、端口、缓存区大小等。

public class MyNettyServer {
	
	private EventLoopGroup acceptGroup;
	private EventLoopGroup dealGroup;
	private ServerBootstrap bootstrap;
	private int port;
	
	public MyNettyServer(int port) {
		this.port = port;
		init();
	}
	
	/**
	 * 初始化
	 * 初始化线程组、服务配置
	 */
	private void init() {
		// 初始化线程组,构建线程组的时候,如果不传递参数,则默认构建的线程组线程数是CPU核心数量。
		acceptGroup = new NioEventLoopGroup();
		dealGroup = new NioEventLoopGroup();
		
		// 初始化服务的配置
		bootstrap = new ServerBootstrap();
		
		// 绑定线程组
		bootstrap.group(acceptGroup, dealGroup);
		
		// 设定通讯模式为NIO, 同步非阻塞
		bootstrap.channel(NioServerSocketChannel.class);
		
		// 设定缓冲区大小, 缓存区的单位是字节。
		bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
		// SO_SNDBUF发送缓冲区,SO_RCVBUF接收缓冲区,SO_KEEPALIVE开启心跳监测(保证连接有效)
		bootstrap.option(ChannelOption.SO_SNDBUF, 8*1024)
			.option(ChannelOption.SO_RCVBUF, 8*1024)
			.option(ChannelOption.SO_KEEPALIVE, true);
	}
	
	/**
	 * 执行监听处理逻辑
	 * @return
	 * @throws InterruptedException
	 */
	public ChannelFuture execAccept() throws InterruptedException {
		bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {

			@Override
			protected void initChannel(SocketChannel socketChannel) throws Exception {
				socketChannel.pipeline().addLast(new MyNettyServerHandler());
			}
			
		});
		// bind方法 - 绑定监听端口的。ServerBootstrap可以绑定多个监听端口。 多次调用bind方法即可
		// sync - 开始监听逻辑。 返回一个ChannelFuture。 返回结果代表的是监听成功后的一个对应的未来结果
		// 可以使用ChannelFuture实现后续的服务器和客户端的交互。
		ChannelFuture future = bootstrap.bind(port).sync();
		return future;
	}
	
	/**
	 * 关闭
	 */
	public void release() {
		acceptGroup.shutdownGracefully();
		dealGroup.shutdownGracefully();
	}

	public static void main(String[] args) {
		MyNettyServer server = null;
		ChannelFuture future = null;
		try {
			server = new MyNettyServer(8888);
			future = server.execAccept();
			System.out.println("server start...");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(null != future){
				try {
					future.channel().closeFuture().sync();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			if(null != server){
				server.release();
			}
		}
		
	}

}

server handler:

       继承ChannelHandlerAdapter类,覆写channelRead方法,在该方法中写对应的业务逻辑。

public class MyNettyServerHandler extends ChannelHandlerAdapter {

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		// ByteBuf - netty提供的类,对NIO中的ByteBuffer进行了包装,使用时不再需要去flip
		ByteBuf buf = (ByteBuf)msg;
		// 开辟有效长度的字节数组大小
		byte[] bytes = new byte[buf.readableBytes()];
		// 将缓存中的数据读取到字节数组中。
		buf.readBytes(bytes);
		String message = new String(bytes,"UTF-8");
		System.out.println("client: " + message);
		String backMsg = "server: accept your message '" + message + "'.";
		// 写操作自动释放缓存,避免内存溢出问题。
		ctx.writeAndFlush(Unpooled.copiedBuffer(backMsg.getBytes("UTF-8")));
	}
}

client:

       与server类同

public class MyNettyClient {

	private EventLoopGroup dealGroup;
	private Bootstrap bootstrap;
	private int port;
	private String host;
	
	public MyNettyClient(String host,int port) {
		this.host = host;
		this.port = port;
		init();
	}
	
	private void init() {
		dealGroup = new NioEventLoopGroup();
		bootstrap = new Bootstrap();
		
		bootstrap.group(dealGroup);
		
		// 设定通讯模式为NIO, 同步非阻塞
		bootstrap.channel(NioSocketChannel.class);
		
		// 设定缓冲区大小, 缓存区的单位是字节。
		bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
		// SO_SNDBUF发送缓冲区,SO_RCVBUF接收缓冲区,SO_KEEPALIVE开启心跳监测(保证连接有效)
		bootstrap.option(ChannelOption.SO_SNDBUF, 8*1024)
			.option(ChannelOption.SO_RCVBUF, 8*1024)
			.option(ChannelOption.SO_KEEPALIVE, true);
	}
	
	public ChannelFuture execCon() throws InterruptedException {
		
		bootstrap.handler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel socketChannel) throws Exception {
				socketChannel.pipeline().addLast(new MyNettyClientHandler());
			}
		});
		// 连接服务端
		ChannelFuture future = bootstrap.connect(host, port).sync();
		return future;
	}
	
	public static void main(String[] args) {
		ChannelFuture future = null;
		MyNettyClient client = new MyNettyClient("127.0.0.1",8888);
		
		try {
			future = client.execCon();
			Scanner scan = new Scanner(System.in);
			String msg = null;
			while(true) {
				Thread.sleep(700);
				System.out.print("enter->");
				msg = scan.nextLine();
				if("0".equals(msg)) {
					// addListener - 增加监听,当某条件满足的时候,触发监听器。
					// ChannelFutureListener.CLOSE - 关闭监听器,代表ChannelFuture执行返回后,关闭连接。
					future.channel().writeAndFlush(Unpooled.copiedBuffer(msg.getBytes("UTF-8")))
						.addListener(ChannelFutureListener.CLOSE);
					break;
				}
				// 写数据
				future.channel().writeAndFlush(Unpooled.copiedBuffer(msg.getBytes("UTF-8")));
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(future!=null) {
				try {
					future.channel().closeFuture().sync();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(client!=null) {
				client.dealGroup.shutdownGracefully();
			}
		}
	}

}

client  handler:

        与server handler类同

public class MyNettyClientHandler extends ChannelHandlerAdapter {
	
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		ByteBuf buf = (ByteBuf)msg;
		byte[] bytes = new byte[buf.readableBytes()];
		buf.readBytes(bytes);
		String message = new String(bytes,"UTF-8");
		System.out.println(message);
		// 用于释放缓存。避免内存溢出
		ReferenceCountUtil.release(msg);
	}
}

猜你喜欢

转载自blog.csdn.net/a15123837995/article/details/87098218