netty Demo

今天写了一个helloworld版本的netty程序,跟大家分享一下:

首先需要的包是:netty-all-4.1.25.Final.jar

客户端:

StrClient.java

package client;

import java.net.InetSocketAddress;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ChannelFactory;
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;

/**
*1. 搞一个Bootstrop 对象
*
*2. 封装Bootstrop 对象
*
*3. 写Handler类 也就是所有的业务逻辑
*
* @author zx
*
*/
public class StrClient {
//分配一个ip和端口号
private String host;
private int port;
private NioEventLoopGroup nioEventLoopGroup;
public StrClient(String host, int port) {
this.host = host;
this.port = port;
}

//启动项目 ip地址是 本地 端口号是888
public static void main(String[] args) throws InterruptedException {
new StrClient("localhost", 888).start();
}

public void start() throws InterruptedException {
try {
//客户端的引导类,启动网络客户端 Bootstrap有很多客户端的属性
Bootstrap bootstrap = new Bootstrap();
//可以理解成是一个线程池,用这个线程池来处理连接和接收数据
nioEventLoopGroup = new NioEventLoopGroup();
bootstrap.group(nioEventLoopGroup) //多线程处理,注册一下这个组
.channel(NioSocketChannel.class) //制定通道类型是NioSocketChannel
.remoteAddress(new InetSocketAddress(host, port)) //注册远程服务器的地址
.handler(new ChannelInitializer<SocketChannel>() {
//////////////↑模板代码/////////////
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//业务逻辑
ch.pipeline().addLast(new StrClientHandler());
}
//////////////↓模板代码/////////////
});
//开始连接服务器
ChannelFuture channelFuture = bootstrap.connect().sync(); //等到连接成功,否则一直阻塞线程
channelFuture.channel().closeFuture().sync(); //接收数据之后阻塞
} catch (Exception e) {
e.printStackTrace();
} finally {
nioEventLoopGroup.shutdownGracefully().sync();
}
}
}

StrClientHandler.java

package client;

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

public class StrClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

//客户端连接服务器后会调用 这里面可以发送请求
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("client -> 开始连接服务器发送数据...");
byte[] bytes = "get current time".getBytes();
ByteBuf buffer = Unpooled.buffer(bytes.length); //构造一个数组存数据
buffer.writeBytes(bytes); //给buffer写数据 在数组里面写入的数据
ctx.writeAndFlush(buffer); //将这个信息交给上下文 进入pipline 如果有第二个Handler也会把这个数据给这第二个Handler
}

//从服务器端接到数据之后
@Override
protected void channelRead0(ChannelHandlerContext ch, ByteBuf msg) throws Exception {
System.out.println("client -> 读取服务器返回的对象...");
//反序列化
byte [] bytes = new byte [msg.readableBytes()]; //将这个2进制的数据写入数组里
msg.readBytes(bytes); //实际上是写入数组中
String messageBody = new String (bytes,"UTF-8");
System.out.println("client -> 接到数据,内容是: " + messageBody);
}

//发生异常的时候会调用
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//打印出错的原因
cause.printStackTrace();
//发生异常的时候就会关闭这个上下文,中断数据的传输
ctx.close();
}

}

服务端:

StrServer.java

package server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class StrServer {
private int port;
private NioEventLoopGroup nioEventLoopGroup;

public StrServer(int port) {
this.port = port;
}

public static void main(String[] args) throws InterruptedException {
new StrServer(888).start();
}

private void start() throws InterruptedException {
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
nioEventLoopGroup = new NioEventLoopGroup();
serverBootstrap.group(nioEventLoopGroup)
.channel(NioServerSocketChannel.class)
.localAddress("localhost", port)
.childHandler(new ChannelInitializer<Channel>() {
//业务逻辑
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new StrServerHandler());
}
});
ChannelFuture channelFuture = serverBootstrap.bind().sync();
System.out.println("Server -> 服务启动成功 监听端口, " + port);
channelFuture.channel().closeFuture().sync();
}catch (Exception e) {
e.printStackTrace();
} finally {
nioEventLoopGroup.shutdownGracefully().sync();
}
}
}

StrServerHandler.java

package server;

import java.util.Date;

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

public class StrServerHandler extends ChannelInboundHandlerAdapter {

/**
*
*@param ctx 上下文
*@param msg 传来的具体的数据
*
*/
//读取客户端发来的数据 这个方法会被调起,在服务器读取数据的时候
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("Server -> 接到数据,开始处理...");
ByteBuf buf = (ByteBuf)msg; //将传过来的ByteBuf强制转换
byte [] req = new byte[buf.readableBytes()]; //2进制数组
buf.readBytes(req); //将req的内容写到buf中
//反序列化
String requestbody = new String (req, "UTF-8");
System.out.println("Server -> 客户端请求数据是: " + requestbody);
System.out.println("Server -> 开始写回数据");
String currentTime = new Date().toString();
//封装了数据的输出
ByteBuf copiedBuffer = Unpooled.copiedBuffer(currentTime.getBytes());
ctx.write(copiedBuffer);

}

//数据读取完成会调起
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}


//发生异常会被调用
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
cause.printStackTrace();
}
}

运行服务端和客户端的main即可启动服务,

1. 服务端准备接受客户端的请求信息;

2. 客户端请求: get currentTime 

3. 服务端获取到请求信息:get currentTime

4. 服务端准备返回数据: String responseBody = new Date() . toString();

5. 服务端返回数据

6. 客户端获取服务端返回的数据

原文地址:https://www.cnblogs.com/zx947240023/p/9178843.html