Server示例代码:
/**
* @program: learnnetty
* @description: 事件传播
* @create: 2020-05-08 16:40
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new InboundHandlerA())
.addLast(new InboundHandlerB())
.addLast(new InboundHandlerC());
}
});
bootstrap.bind("127.0.0.1", 8080);
}
}
处理器A示例代码:
/**
* @program: learnnetty
* @description: 处理器A
* @create: 2020-05-08 16:41
**/
public class InboundHandlerA extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf)msg;
System.out.println("InboundHandlerA:" + byteBuf.toString(StandardCharsets.UTF_8));
byteBuf.writeBytes(",A add".getBytes());
ctx.fireChannelRead(byteBuf);
}
}
处理器B示例代码:
/**
* @program: learnnetty
* @description: 处理器B
* @create: 2020-05-08 16:42
**/
public class InboundHandlerB extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf)msg;
System.out.println("InboundHandlerB:" + byteBuf.toString(StandardCharsets.UTF_8));
byteBuf.writeBytes(",B add".getBytes());
ctx.fireChannelRead(byteBuf);
}
}
处理器C示例代码:
/**
* @program: learnnetty
* @description: 处理器C
* @create: 2020-05-08 16:42
**/
public class InboundHandlerC extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf)msg;
System.out.println("InboundHandlerC:" + byteBuf.toString(StandardCharsets.UTF_8));
byteBuf.writeBytes(",C add".getBytes());
ctx.fireChannelRead(byteBuf);
}
}
输出:
InboundHandlerA:123
InboundHandlerB:123,A add
InboundHandlerC:123,A add,B add
如果有需要在处理链上传播,则可以使用ChannelHandlerContext.fireChannelRead()将当前以完成处理的数据交由下一个处理器处理。
修改后的Server示例代码:
/**
* @program: learnnetty
* @description: 事件传播
* @create: 2020-05-08 16:40
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new InboundHandlerA())
.addLast(new OutboundHandlerA())
.addLast(new OutboundHandlerB())
.addLast(new OutboundHandlerC());
}
});
bootstrap.bind("127.0.0.1", 8080);
}
}
做出反馈的InboundHandlerA示例代码:
/**
* @program: learnnetty
* @description: 处理器A
* @create: 2020-05-08 16:41
**/
public class InboundHandlerA extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("收到:" + msg);
ctx.channel().writeAndFlush(Unpooled.wrappedBuffer("321".getBytes()));
}
}
OutboundHandlerA示例代码:
/**
* @program: learnnetty
* @description: 处理器A
* @create: 2020-05-08 16:54
**/
public class OutboundHandlerA extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutA");
ByteBuf byteBuf = (ByteBuf)msg;
//需要发送的信息
String msgStr = ",A add";
//旧的ByteBuf可写入字符数为0,新建一个
ByteBuf buf = ctx.alloc().ioBuffer(byteBuf.readableBytes() + msgStr.getBytes().length);
//旧数据
byte[] oldData = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(oldData);
//新旧数据写入新的ByteBuf
buf.writeBytes(oldData);
buf.writeBytes(msgStr.getBytes());
System.out.println("A updated msg");
//释放旧的ByteBuf
byteBuf.release();
//传递
ctx.write(buf, promise);
}
}
OutboundHandlerB示例代码:
/**
* @program: learnnetty
* @description: 处理器B
* @create: 2020-05-08 16:55
**/
public class OutboundHandlerB extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutB");
ByteBuf byteBuf = (ByteBuf)msg;
//需要发送的信息
String msgStr = ",B add";
//旧的ByteBuf可写入字符数为0,新建一个
ByteBuf buf = ctx.alloc().ioBuffer(byteBuf.readableBytes() + msgStr.getBytes().length);
//旧数据
byte[] oldData = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(oldData);
//新旧数据写入新的ByteBuf
buf.writeBytes(oldData);
buf.writeBytes(msgStr.getBytes());
System.out.println("B updated msg");
//释放旧的ByteBuf
byteBuf.release();
//传递
ctx.write(buf, promise);
}
}
OutboundHandlerC示例代码:
/**
* @program: learnnetty
* @description: 处理器C
* @create: 2020-05-08 16:55
**/
public class OutboundHandlerC extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutC");
ByteBuf byteBuf = (ByteBuf)msg;
//需要发送的信息
String msgStr = ",C add";
//旧的ByteBuf可写入字符数为0,新建一个
ByteBuf buf = ctx.alloc().ioBuffer(byteBuf.readableBytes() + msgStr.getBytes().length);
//旧数据
byte[] oldData = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(oldData);
//新旧数据写入新的ByteBuf
buf.writeBytes(oldData);
buf.writeBytes(msgStr.getBytes());
System.out.println("C updated msg");
//释放旧的ByteBuf
byteBuf.release();
//传递
ctx.write(buf, promise);
}
}
输出:
收到:PooledUnsafeDirectByteBuf(ridx: 0, widx: 3, cap: 1024)
OutC
C updated msg
OutB
B updated msg
OutA
A updated msg
因为传入的ByteBuf可写入字节数为0,因此要添加新的数据需要新建一个ByteBuf,用新建的ByteBuf替换掉旧的ByteBuf用于存储添加的数据。
本人新手一枚,在学习InboundHandler传递链时突发奇想,在OutboundHandler传递数据时是不是也能这么做,所以才有了以上代码,尚不清楚这样代码有何影响。
用于解析二进制数据包的FrameDecoder.java
/**
* @program: learnnetty
* @description: 解码
* @create: 2020-05-08 20:14
**/
public class FrameDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
list.add(ParseFrame.getInstance().decode(byteBuf));
}
}
值的注意的是如果使用ByteToMessageDecoder进行解码的话,在此处使用的ByteBuf会被自动释放,而非手动释放。
修改后的客户端Client:
/**
* @program: learnnetty
* @description: 客户端
* @create: 2020-05-06 15:39
**/
public class Client {
private static final int MAX_RETRY = 5;
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap
.group(workerGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new FrameDecoder())
.addLast(new ClientLoginHandler())
.addLast(new ClientMsgHandler());
}
});
connect(bootstrap, "127.0.0.1", 8080, MAX_RETRY);
}
private static void connect(final Bootstrap bootstrap, final String host, final int port, final int retry){
bootstrap.connect(host, port).addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
if (future.isSuccess()){
System.out.println("客户端连接成功");
Channel channel = ((ChannelFuture)future).channel();
startConsoleThread(channel);
}else if (retry == 0){
System.out.println("客户端连接失败次数过多,放弃连接");
}else {
System.out.println("客户端连接失败,尝试重连");
int order = MAX_RETRY - retry + 1;
int delay = 1 << order;
System.out.println(new Date() + " 连接失败,第" + order + "次连接");
bootstrap.config().group().schedule(new Runnable() {
@Override
public void run() {
connect(bootstrap, host, port, retry - 1);
}
}, delay, TimeUnit.SECONDS);
}
}
});
}
private static void startConsoleThread(final Channel channel){
new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()){
if (LoginUtil.hasLogin(channel)){
System.out.println("输入消息发送至服务端:");
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
MsgRequestFrame requestFrame = new MsgRequestFrame();
requestFrame.setContent(line);
ByteBuf byteBuf = ParseFrame.getInstance().encode(channel.alloc(), requestFrame);
channel.writeAndFlush(byteBuf);
}
}
}
}).start();
}
}
拆解后的ClientLoginHandler:
/**
* @program: learnnetty
* @description: 服务端处理信息
* @create: 2020-05-08 20:36
**/
public class ClientLoginHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println(new Date() + ",客户端开始登录");
LoginRequestFrame loginFrame = new LoginRequestFrame();
loginFrame.setUserId(UUID.randomUUID().toString());
loginFrame.setUserName("zcd");
loginFrame.setPassword("zzz");
ByteBuf buf = ParseFrame.getInstance().encode(ctx.alloc(), loginFrame);
ctx.channel().writeAndFlush(buf);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
BaseFrame frame = (BaseFrame) msg;
if (frame instanceof LoginResponseFrame){
LoginResponseFrame responseFrame = (LoginResponseFrame) frame;
if (responseFrame.isSuccess()){
LoginUtil.markAsLogin(ctx.channel());
System.out.println("客户端登录成功");
}else {
System.out.println("客户端登录失败,原因:" + responseFrame.getMsg());
}
}else {
ctx.fireChannelRead(frame);
}
}
}
拆解后的ClientMsgHandler:
/**
* @program: learnnetty
* @description: 信息响应Handler
* @create: 2020-05-08 20:26
**/
public class ClientMsgHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
BaseFrame frame = (BaseFrame) msg;
if (frame instanceof MsgResponseFrame){
MsgResponseFrame responseFrame = (MsgResponseFrame) frame;
System.out.println(new Date() + ",收到来自服务器的消息:" + responseFrame.getContent());
}else {
ctx.fireChannelRead(frame);
}
}
}
修改后的服务端Server:
/**
* @program: learnnetty
* @description: 服务端
* @create: 2020-05-06 17:18
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new FrameDecoder())
.addLast(new ServerLoginHandler())
.addLast(new ServerMsgHandler());
}
});
bind(serverBootstrap, 8080);
}
private static void bind(final ServerBootstrap serverBootstrap, final int port){
serverBootstrap.bind(port).addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
if (future.isSuccess()){
System.out.println("端口[" + port + "]绑定成功");
}else {
System.out.println("端口[" + port + "]绑定失败,尝试绑定[" + (port + 1) + "]端口");
bind(serverBootstrap, port + 1);
}
}
});
}
}
拆解后的ServerLoginHandler:
/**
* @program: learnnetty
* @description: 服务端处理
* @create: 2020-05-06 17:19
**/
public class ServerLoginHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(new Date() + ",服务端开始处理请求");
BaseFrame baseFrame = (BaseFrame)msg;
if (baseFrame instanceof LoginRequestFrame){
LoginRequestFrame requestFrame = (LoginRequestFrame)baseFrame;
LoginResponseFrame responseFrame = new LoginResponseFrame();
responseFrame.setUserId(requestFrame.getUserId());
responseFrame.setUserName(requestFrame.getUserName());
if(requestFrame.getUserName().equals("zcd") && requestFrame.getPassword().equals("zzz")){
responseFrame.setSuccess(true);
responseFrame.setMsg("登录成功");
System.out.println(new Date() + ",zcd客户端登录成功");
}else {
responseFrame.setSuccess(false);
responseFrame.setMsg("密码或用户名错误");
System.out.println(new Date() + ",zcd客户端登录失败");
}
ByteBuf respByteBuf = ParseFrame.getInstance().encode(ctx.alloc(), responseFrame);
ctx.channel().writeAndFlush(respByteBuf);
}else {
ctx.fireChannelRead(baseFrame);
}
}
}
拆解后的ServerMsgHandler:
/**
* @program: learnnetty
* @description: 服务端处理信息
* @create: 2020-05-08 20:36
**/
public class ServerMsgHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
BaseFrame baseFrame = (BaseFrame) msg;
if (baseFrame instanceof MsgRequestFrame){
MsgRequestFrame msgRequestFrame = (MsgRequestFrame)baseFrame;
System.out.println(new Date() + ",收到来自客户端的消息:" + msgRequestFrame.getContent());
MsgResponseFrame responseFrame = new MsgResponseFrame();
responseFrame.setContent("服务器已收到消息");
ByteBuf respByteBuf = ParseFrame.getInstance().encode(ctx.alloc(), responseFrame);
ctx.channel().writeAndFlush(respByteBuf);
}else {
ctx.fireChannelRead(baseFrame);
}
}
}
客户端输出:
客户端连接成功
Fri May 08 20:41:16 CST 2020,客户端开始登录
客户端登录成功
输入消息发送至服务端:
123
输入消息发送至服务端:
Fri May 08 20:41:19 CST 2020,收到来自服务器的消息:服务器已收到消息
服务端输出:
端口[8080]绑定成功
Fri May 08 20:41:16 CST 2020,服务端开始处理请求
Fri May 08 20:41:16 CST 2020,zcd客户端登录成功
Fri May 08 20:41:19 CST 2020,服务端开始处理请求
Fri May 08 20:41:19 CST 2020,收到来自客户端的消息:123
值的注意的是客户端和服务端在FrameDecoder之后传递的都是BaseFrame而非ByteBuf。
抽取方法并使用编码类之后的Client示例代码:
/**
* @program: learnnetty
* @description: 客户端
* @create: 2020-05-06 15:39
**/
public class Client {
private static final int MAX_RETRY = 5;
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap
.group(workerGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new FrameDecoder())
.addLast(new ClientLoginHandler())
.addLast(new ClientMsgHandler())
.addLast(new FrameEncoder());
}
});
connect(bootstrap, "127.0.0.1", 8080, MAX_RETRY);
}
private static void connect(final Bootstrap bootstrap, final String host, final int port, final int retry){
bootstrap.connect(host, port).addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
if (future.isSuccess()){
System.out.println("客户端连接成功");
Channel channel = ((ChannelFuture)future).channel();
startConsoleThread(channel);
}else if (retry == 0){
System.out.println("客户端连接失败次数过多,放弃连接");
}else {
System.out.println("客户端连接失败,尝试重连");
int order = MAX_RETRY - retry + 1;
int delay = 1 << order;
System.out.println(new Date() + " 连接失败,第" + order + "次连接");
bootstrap.config().group().schedule(new Runnable() {
@Override
public void run() {
connect(bootstrap, host, port, retry - 1);
}
}, delay, TimeUnit.SECONDS);
}
}
});
}
private static void startConsoleThread(final Channel channel){
new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()){
if (LoginUtil.hasLogin(channel)){
System.out.println("输入消息发送至服务端:");
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
channel.writeAndFlush(MsgUtil.reqMsg(line));
}
}
}
}).start();
}
}
使用编码器之后的Server示例代码:
/**
* @program: learnnetty
* @description: 服务端
* @create: 2020-05-06 17:18
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new FrameDecoder())
.addLast(new ServerLoginHandler())
.addLast(new ServerMsgHandler())
.addLast(new FrameEncoder());
}
});
bind(serverBootstrap, 8080);
}
private static void bind(final ServerBootstrap serverBootstrap, final int port){
serverBootstrap.bind(port).addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
if (future.isSuccess()){
System.out.println("端口[" + port + "]绑定成功");
}else {
System.out.println("端口[" + port + "]绑定失败,尝试绑定[" + (port + 1) + "]端口");
bind(serverBootstrap, port + 1);
}
}
});
}
}
新建的编码器类FrameEncoder示例代码:
/**
* @program: learnnetty
* @description: 编码
* @create: 2020-05-09 10:57
**/
public class FrameEncoder extends MessageToByteEncoder<BaseFrame> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, BaseFrame baseFrame, ByteBuf byteBuf) throws Exception {
ParseFrame.getInstance().encode(byteBuf, baseFrame);
}
}
抽取方法之后的ClientLoginHandler处理器类示例代码:
/**
* @program: learnnetty
* @description: 客户端业务处理
* @create: 2020-05-06 15:40
**/
public class ClientLoginHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println(new Date() + ",客户端开始登录");
LoginRequestFrame loginFrame = new LoginRequestFrame();
loginFrame.setUserId(UUID.randomUUID().toString());
loginFrame.setUserName("zcd");
loginFrame.setPassword("zzz");
ctx.channel().writeAndFlush(loginFrame);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
BaseFrame frame = (BaseFrame) msg;
if (frame instanceof LoginResponseFrame){
LoginUtil.resolveRespLoginFrame(frame, ctx);
}else {
ctx.fireChannelRead(frame);
}
}
}
抽取方法之后的ClientMsgHandler处理器类示例代码:
/**
* @program: learnnetty
* @description: 信息响应Handler
* @create: 2020-05-08 20:26
**/
public class ClientMsgHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
BaseFrame frame = (BaseFrame) msg;
if (frame instanceof MsgResponseFrame){
MsgUtil.resolveRespMsg(frame);
}else {
ctx.fireChannelRead(frame);
}
}
}
抽取方法之后的ServerLoginHandler处理器类:
/**
* @program: learnnetty
* @description: 服务端处理
* @create: 2020-05-06 17:19
**/
public class ServerLoginHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(new Date() + ",服务端开始处理请求");
BaseFrame baseFrame = (BaseFrame)msg;
if (baseFrame instanceof LoginRequestFrame){
ctx.channel().writeAndFlush(LoginUtil.respLogin(baseFrame));
}else {
ctx.fireChannelRead(baseFrame);
}
}
}
抽取方法之后的ServerMsgHandler处理器类示例代码:
/**
* @program: learnnetty
* @description: 服务端处理信息
* @create: 2020-05-08 20:36
**/
public class ServerMsgHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
BaseFrame baseFrame = (BaseFrame) msg;
if (baseFrame instanceof MsgRequestFrame){
ctx.channel().writeAndFlush(MsgUtil.respMsg(baseFrame));
}else {
ctx.fireChannelRead(baseFrame);
}
}
}
登录相关工具类LoginUtil示例代码:
/**
* @program: learnnetty
* @description: 登录工具类
* @create: 2020-05-07 16:38
**/
public class LoginUtil {
/**
* 标记登录
*/
public static void markAsLogin(Channel channel){
channel.attr(Attributes.LOGIN).set(true);
}
/**
* 检查是否登录
*/
public static boolean hasLogin(Channel channel){
Attribute<Boolean> loginAttr = channel.attr(Attributes.LOGIN);
if (loginAttr.get() == null){
return false;
}
return loginAttr.get();
}
/**
* 生成响应登录数据包
*/
public static BaseFrame respLogin(BaseFrame baseFrame){
LoginRequestFrame requestFrame = (LoginRequestFrame)baseFrame;
LoginResponseFrame responseFrame = new LoginResponseFrame();
responseFrame.setUserId(requestFrame.getUserId());
responseFrame.setUserName(requestFrame.getUserName());
if(requestFrame.getUserName().equals("zcd") && requestFrame.getPassword().equals("zzz")){
responseFrame.setSuccess(true);
responseFrame.setMsg("登录成功");
System.out.println(new Date() + ",zcd客户端登录成功");
}else {
responseFrame.setSuccess(false);
responseFrame.setMsg("密码或用户名错误");
System.out.println(new Date() + ",zcd客户端登录失败");
}
return responseFrame;
}
/**
* 处理登录响应数据包
*/
public static void resolveRespLoginFrame(BaseFrame frame, ChannelHandlerContext ctx){
LoginResponseFrame responseFrame = (LoginResponseFrame) frame;
if (responseFrame.isSuccess()){
LoginUtil.markAsLogin(ctx.channel());
System.out.println("客户端登录成功");
}else {
System.out.println("客户端登录失败,原因:" + responseFrame.getMsg());
}
}
}
信息相关工具类MsgUtil示例代码:
/**
* @program: learnnetty
* @description: Msg相关处理
* @create: 2020-05-09 11:17
**/
public class MsgUtil {
/**
* 对Msg做出响应
*/
public static BaseFrame respMsg(BaseFrame baseFrame) {
MsgRequestFrame msgRequestFrame = (MsgRequestFrame)baseFrame;
System.out.println(new Date() + ",收到来自客户端的消息:" + msgRequestFrame.getContent());
MsgResponseFrame responseFrame = new MsgResponseFrame();
responseFrame.setContent("服务器已收到消息");
return responseFrame;
}
/**
* 处理反馈的Msg
*/
public static void resolveRespMsg(BaseFrame baseFrame){
MsgResponseFrame responseFrame = (MsgResponseFrame) baseFrame;
System.out.println(new Date() + ",收到来自服务器的消息:" + responseFrame.getContent());
}
/**
* 发送请求Msg
*/
public static BaseFrame reqMsg(String line){
MsgRequestFrame requestFrame = new MsgRequestFrame();
requestFrame.setContent(line);
return requestFrame;
}
}
客户端输出:
客户端连接成功
Sat May 09 11:22:20 CST 2020,客户端开始登录
客户端登录成功
输入消息发送至服务端:
123
输入消息发送至服务端:
Sat May 09 11:22:22 CST 2020,收到来自服务器的消息:服务器已收到消息
服务端输出:
端口[8080]绑定成功
Sat May 09 11:22:20 CST 2020,服务端开始处理请求
Sat May 09 11:22:20 CST 2020,zcd客户端登录成功
Sat May 09 11:22:22 CST 2020,服务端开始处理请求
Sat May 09 11:22:22 CST 2020,收到来自客户端的消息:123