- Rest风格,为一种编码风格。默认约定
NettyHelloword,客户端,和服务器端
package com.netty.c1;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
public class Hello {
//服务器端代码
public static void main(String[] args) {
// 1.启动器,负责组装netty组件,启动服务器
new ServerBootstrap()
//2.包含selector,检测io事件,可连接,可读可写等,+线程,简单理解,包含线程和选择器、
.group(new NioEventLoopGroup())
//3.选择一个ServerSocketChannel的实现。
.channel(NioServerSocketChannel.class)
//4.boss处理连接的,worker(child),负责读写的。决定worker(child)能干那些操作
.childHandler(
//跟客户端连接后,和客户端进行数据读写的通道Initializer 初始化,负责添加别的Handler
new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
// 添加具体的Handler
ch.pipeline().addLast(new StringDecoder());//将byteBuf转为字符串
ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){//自定义handler
@Override//读事件
//NioEventLoopGroup循环接收,当接收到的时候,初始化器会执行
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
//打印上一步转换好的字符串
System.out.println(msg);
}
});
}
})
.bind(8080);
}
}
package com.netty.c1;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import java.net.InetSocketAddress;
public class HelloClient {
public static void main(String[] args) {
//创建启动器类。
try {
new Bootstrap()
//添加选择器,Eventloop
.group(new NioEventLoopGroup())
// 选择客户端channe实现
.channel(NioSocketChannel.class)
// 添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override//在链接调用后被调用,初始化作用
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());//把字符转编码成bytebuf发过去,服务器,吧ByteBuf解码成字符串
}
})
// 链接到服务器
.connect(new InetSocketAddress("localhost",8080))
.sync()
.channel()
.writeAndFlush("hello word");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Netty服务器端详解
package com.netty.c1;
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 static void main(String[] args) {
EventLoopGroup bossGroup=new NioEventLoopGroup();//bossGroup用的是所以是ServerSocketChannel
EventLoopGroup workerGroup=new NioEventLoopGroup();//workerGroup用的是所以是SocketChannel
try {
//创建服务器端启动对象
ServerBootstrap bootstrap=new ServerBootstrap();
bootstrap.group(bossGroup,workerGroup)
.channel(NioServerSocketChannel.class)//因为是服务器端,所以是NioServerSocketChannel,客户端,没有Server
.option(ChannelOption.SO_BACKLOG,128)//设置线程队列等待链接的个数
.childOption(ChannelOption.SO_KEEPALIVE,true)//设置保持活动链接状态
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//这里面的参数new ServerHandler(),为自己创建的类class,
ch.pipeline().addLast(new ServerHandler());
}
});//设置处理器,因为是SocketChannel,所以是给workerGroup的
System.out.println("服务器端ok" );
try {
//启动服务器并绑定端口
ChannelFuture cf=bootstrap.bind(6668).sync();//绑定一个端口并同步, 生成一个ChannelFuture对象
cf.channel().closeFuture().sync();//对关闭通道进行监听。
} catch (InterruptedException e) {
e.printStackTrace(); }
}
finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
package com.netty.c1;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import java.nio.ByteBuffer;
//继承Channel入栈适配器
//我们自定义一个handler,需要继承netty规定好的某个HandlerAdapter 适配器
//这时我们的handler才能称之为handler
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
//读取实际数据,读取客户端发送的数据
//ChannelHandlerContext含有1.管道pipline,通道,channel,地址等所有信息。
// msg就是客户端发送的数据
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("Server,ChannelHandlerContext ctx=:"+ctx);
//将msg转换为一个Bytebuf,是Netty的ByteBuf,性能更高。
ByteBuf buffer=(ByteBuf) msg;
System.out.println("msg:"+buffer.toString(CharsetUtil.UTF_8));
System.out.println("客户端地址:"+ctx.channel().remoteAddress());
}
//数据读取完成后,进行的。
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//把数据写到一个缓冲,同时刷新该缓冲区。是两个方法的合并。;一般情况下,对发送的数据进行编码
ctx.writeAndFlush(Unpooled.copiedBuffer("服务器端发送 :hello 客户端",CharsetUtil.UTF_8));
}
//处理异常的,一般关闭通道
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
Netty客户端详解
package com.netty.c1;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class Client {
public static void main(String[] args)throws Exception
{
//客户端需要一个事件循环组。即可
NioEventLoopGroup group = new NioEventLoopGroup();
try {
//创建一个客户端启动对象 助手
//客户端使用的不是ServerBootstrap,而是Bootstrap
Bootstrap bootstrap = new Bootstrap();
//设置相关参数
bootstrap.group(group)//设置线程组
.channel(NioSocketChannel.class)//设置客户端通道的实现类。(反射)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ClientHandler());//加入自己写的处理器
}
});
System.out.println("客户端ok" );
//启动客户端,去连接服务器端,
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();
//给关闭通道连接,进行监听
channelFuture.channel().closeFuture().sync();
}finally {
group.shutdownGracefully();
}
}
}
package com.netty.c1;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import java.nio.ByteBuffer;
public class ClientHandler extends ChannelInboundHandlerAdapter {
//当通道就绪就会触发
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("client"+ctx);
ctx.writeAndFlush(Unpooled.copiedBuffer("hello server ,im Client", CharsetUtil.UTF_8));
} //当 通道有读取事件时,会触发。读取服务器端返回的数据
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf=(ByteBuf) msg;
System.out.println("服务器回复的消息"+buf.toString(CharsetUtil.UTF_8));
System.out.println("服务器地址"+ctx.channel().remoteAddress());
}
//异常发生时
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}