Netty之HelloWorld

1、关于Netty编程常用类的介绍

        BootStrap和ServerBootstrap类似,不过他是对非服务端的channel而言,比如客户端。

        如果你只指定了一个EventLoopGroup那他就会即作为一个‘boss’线程,也会作为一个‘workder’线程,尽管客户端不需要使用到‘boss’线程。

       代替NioServerSocketChannel的是NioSocketChannel,这个类在客户端channel被创建时使用。 

       不像在使用ServerBootstrap时需要用childOption()方法,因为客户端的SocketChannel没有父channel的概念。在客户端用connect()方法代替了bind()方法。

2、如果在获取消息后,只是进行读数据,没有回写数据。则需要手动的释放msg

public class ClientHandler extends ChannelHandlerAdapter {
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		try {
			ByteBuf buf = (ByteBuf) msg;
			byte[] req = new byte[buf.readableBytes()];
			buf.readBytes(req);

			String body = new String(req, "utf-8");
			System.out.println("Client :" + body);

			// 只是读数据,没有写数据的话
			// 需要自己手动的释放的消息

		} finally {
			ReferenceCountUtil.release(msg);
		}
	}
}
3、关于服务端长连接和短连接的实现

      当服务端完成一次数据响应后,断开与客户端的连接,就是短连接。在Netty中可以设置,服务端在响应数据完成后,关闭与客户端的连接。也就是短连接的实现。

public class ServerHandler extends ChannelHandlerAdapter {
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		// 接受客户端的数据
		ByteBuf buf = (ByteBuf) msg;
		byte[] req = new byte[buf.readableBytes()];
		buf.readBytes(req);
		String body = new String(req, "utf-8");
		System.out.println("Server: from client " + body);
		// 服务端,回写数据给客户端
		String response = "Hi Client,I am Server ... ";
		ByteBuf resp = Unpooled.copiedBuffer(response.getBytes());
		ctx.writeAndFlush(resp);

		// 当服务端完成写操作后,关闭与客户端的连接
		// ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()))
		// .addListener(ChannelFutureListener.CLOSE);

		// 上面就是长连接和短连接的实现
		// 关闭应该是通过Server端来完成,因为在客户端写数据完成后,关闭连接的话。就接受不到服务端的数据了
		// 如果只是读数据,就要释放msg
		// 如果用了,write就不需要手动的释放msg了

	}
}

4、服务端的实现

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;

public class Server {
	public void bind(int port) throws Exception {
		// 服务器线程组 用于网络事件的处理 一个用于服务器接收客户端的连接
		// 另一个线程组用于处理SocketChannel的网络读写
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			// NIO服务器端的辅助启动类 降低服务器开发难度
			ServerBootstrap serverBootstrap = new ServerBootstrap();
			serverBootstrap.group(bossGroup, workerGroup)
					.channel(NioServerSocketChannel.class)// 类似NIO中serverSocketChannel
					.option(ChannelOption.SO_BACKLOG, 1024)// 配置TCP参数
					.option(ChannelOption.SO_BACKLOG, 1024) // 设置tcp缓冲区
					.option(ChannelOption.SO_SNDBUF, 32 * 1024) // 设置发送缓冲大小
					.option(ChannelOption.SO_RCVBUF, 32 * 1024) // 这是接收缓冲大小
					.option(ChannelOption.SO_KEEPALIVE, true) // 保持连接
					.childHandler(new ChildChannelHandler());// 最后绑定I/O事件的处理类
																// 处理网络IO事件

			// 服务器启动后 绑定监听端口 同步等待成功 主要用于异步操作的通知回调 回调处理用的ChildChannelHandler
			ChannelFuture f = serverBootstrap.bind(port).sync();
			System.out.println("Server启动");
			// 等待服务端监听端口关闭
			f.channel().closeFuture().sync();

		} finally {
			// 优雅退出 释放线程池资源
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
			System.out.println("服务器优雅的释放了线程资源...");
		}

	}

	/**
	 * 网络事件处理器
	 */
	private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
		@Override
		protected void initChannel(SocketChannel ch) throws Exception {
			ch.pipeline().addLast(new ServerHandler());
		}
	}

	public static void main(String[] args) throws Exception {
		int port = 9998;
		new Server().bind(port);
	}
}
5、服务端Handler的实现

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

public class ServerHandler extends ChannelHandlerAdapter {

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		// 接受客户端的数据
		ByteBuf buf = (ByteBuf) msg;
		byte[] req = new byte[buf.readableBytes()];
		buf.readBytes(req);
		String body = new String(req, "utf-8");
		System.out.println("Server: from client " + body);
		// 服务端,回写数据给客户端
		String response = "Hi Client,I am Server ... ";
		ByteBuf resp = Unpooled.copiedBuffer(response.getBytes());
		ctx.writeAndFlush(resp);

		// 当服务端完成写操作后,关闭与客户端的连接
		// ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()))
		// .addListener(ChannelFutureListener.CLOSE);

		// 上面就是长连接和短连接的实现
		// 关闭应该是通过Server端来完成,因为在客户端写数据完成后,关闭连接的话。就接受不到服务端的数据了
		// 如果只是读数据,就要释放msg
		// 如果用了,write就不需要手动的释放msg了

	}

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

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}
}
6、客户端的实现

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
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.NioSocketChannel;

public class Client {
	/**
	 * 连接服务器
	 * 
	 * @param port
	 * @param host
	 * @throws Exception
	 */
	public void connect(int port, String host) throws Exception {
		// 配置客户端NIO线程组
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			// 客户端辅助启动类 对客户端配置
			Bootstrap b = new Bootstrap();
			b.group(group)//
					.channel(NioSocketChannel.class)//
					.option(ChannelOption.TCP_NODELAY, true)//
					.handler(new ClientChannelHandler());//
			// 异步链接服务器 同步等待链接成功
			ChannelFuture f = b.connect(host, port).sync();

			// 发送消息
			Thread.sleep(1000);
			f.channel().writeAndFlush(Unpooled.copiedBuffer("777".getBytes()));
			f.channel().writeAndFlush(Unpooled.copiedBuffer("666".getBytes()));
			Thread.sleep(2000);
			f.channel().writeAndFlush(Unpooled.copiedBuffer("888".getBytes()));

			// 等待链接关闭
			f.channel().closeFuture().sync();

		} finally {
			group.shutdownGracefully();
			System.out.println("客户端优雅的释放了线程资源...");
		}

	}

	/**
	 * 网络事件处理器
	 */
	private class ClientChannelHandler extends
			ChannelInitializer<SocketChannel> {
		@Override
		protected void initChannel(SocketChannel ch) throws Exception {
			ch.pipeline().addLast(new ClientHandler());
		}

	}

	public static void main(String[] args) throws Exception {
		new Client().connect(9998, "127.0.0.1");

	}
}
7、客户端Handler的实现

import io.netty.buffer.ByteBuf;
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 {
		try {
			ByteBuf buf = (ByteBuf) msg;
			byte[] req = new byte[buf.readableBytes()];
			buf.readBytes(req);

			String body = new String(req, "utf-8");
			System.out.println("Client :" + body);

			// 只是读数据,没有写数据的话
			// 需要自己手动的释放的消息

		} finally {
			ReferenceCountUtil.release(msg);
		}
	}

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

}
8、 源码下载


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用Netty搭建TCP服务器的示例代码(Hello World): ```java import io.netty.bootstrap.ServerBootstrap; 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.NioServerSocketChannel; public class HelloWorldServer { private final int port; public HelloWorldServer(int port) { this.port = port; } public void run() throws Exception { // 创建两个 EventLoopGroup,一个用于接收客户端连接,一个用于处理客户端请求 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { // 创建 ServerBootstrap 对象,用于配置服务器 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 添加消息处理器 ch.pipeline().addLast(new HelloWorldServerHandler()); } }); // 绑定端口,开始接收客户端请求 ChannelFuture f = b.bind(port).sync(); // 等待服务器 socket 关闭 f.channel().closeFuture().sync(); } finally { // 释放资源 workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port = 8080; new HelloWorldServer(port).run(); } } ``` 其中,`HelloWorldServerHandler` 是自定义的消息处理器,可以根据需要进行处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值