Netty简单实现客户端与服务端收发消息

这个小案例主要是实现netty收发消息,分为客户端,及服务端,以及包含了相关状态处理,主要的代码会放在最后 gitHub 地址上,有需要可以看一下
首先来简单说明一下消息收发流程

1.客户端构建登录请求对象,服务端判断登录是否成功,并绑定成功状态
2.客户端判断登录成功,构建消息请求对象接收消息
3.服务端接收消息后进行处理,并构建消息返回对象,进行返回
4.客户端接收消息返回对象处理,流程结束

一 创建消息对象及状态新增
收发消息对象
消息请求对象 :

@Data
public class MessageRequestPacket extends Packet {/*** 消息体*/private String message;@Overridepublic Byte getCommand() {return MESSAGE_REQUEST;}
}

消息返回对象 :

@Data
public class MessageResponsePacket extends Packet {/*** 消息体*/private String message;@Overridepublic Byte getCommand() {return MESSAGE_RESPONSE;}
}

指令新增 :

public interface Command {Byte LOGIN_REQUEST = 1;Byte LOGIN_RESPONSE = 2;Byte MESSAGE_REQUEST = 3;Byte MESSAGE_RESPONSE = 4;
}

解码处理 :

public class PacketCodeC {private static final int MAGIC_NUMBER = 0X12345678;public static final PacketCodeC INSTANCE = new PacketCodeC();private final Map<Byte,Class<? extends Packet>> packetTypeMap;private final Map<Byte,Serializer> serializerMap;public PacketCodeC() {packetTypeMap = new HashMap<>();packetTypeMap.put(LOGIN_REQUEST, LoginRequestPacket.class);packetTypeMap.put(LOGIN_RESPONSE, LoginResponsePacket.class);packetTypeMap.put(MESSAGE_REQUEST, MessageRequestPacket.class);packetTypeMap.put(MESSAGE_RESPONSE, MessageResponsePacket.class);serializerMap = new HashMap<>();JSONSerializer serializer = new JSONSerializer();serializerMap.put(serializer.getSerializerAlgorithm(),serializer);}/*** 编码* @param packet* @return*/public ByteBuf encode(ByteBuf byteBuf,Packet packet) {byte[] bytes = Serializer.DEFAULT.serialize(packet);//魔数byteBuf.writeInt(MAGIC_NUMBER);//版本号byteBuf.writeByte(packet.getVersion());//序列化算法byteBuf.writeByte(Serializer.DEFAULT.getSerializerAlgorithm());//指令byteBuf.writeByte(packet.getCommand());//数据长度byteBuf.writeInt(bytes.length);//数据byteBuf.writeBytes(bytes);return byteBuf;}public Packet decode(ByteBuf byteBuf) {//跳过魔数byteBuf.skipBytes(4);//跳过版本号byteBuf.skipBytes(1);//序列化算法标识byte serializerAlgorithm = byteBuf.readByte();//指令byte command = byteBuf.readByte();//数据包长度int length = byteBuf.readInt();//数据byte[] bytes = new byte[length];byteBuf.readBytes(bytes);Class<? extends Packet> requestType = getRequestType(command);Serializer serializer = getSerializer(serializerAlgorithm);if (requestType != null && serializer != null){return serializer.deserialize(requestType,bytes);}return null;}private Serializer getSerializer(byte serializerAlgorithm) {return serializerMap.get(serializerAlgorithm);}private Class<? extends Packet> getRequestType(byte command) {return packetTypeMap.get(command);}
}

二 判断是否登录
1.登录成功标志位定义

public interface Attributes {AttributeKey<Boolean> LOGIN = AttributeKey.newInstance("login");
}

ClientHandler 登录成功状态处理

if (packet instanceof LoginRequestPacket) {LoginRequestPacket loginResponsePacket = (LoginRequestPacket) packet;if (loginResponsePacket.getSuccess().equals(Boolean.TRUE)) {LoginUtil.markAsLogin(ctx.channel());System.out.println(new Date() + ": 客户端登录成功");}else {System.out.println(new Date() + ": 客户端登录失败,失败原因 : " +loginResponsePacket.getReason());}}

上面代码主要在于 LoginUtil.markAsLogin(ctx.channel());这部分 状态的修改

public class LoginUtil {public static void markAsLogin(Channel channel) {channel.attr(Attributes.LOGIN).set(Boolean.TRUE);}public static boolean hasLogin(Channel channel) {Attribute<Boolean> loginAttr = channel.attr(Attributes.LOGIN);return loginAttr.get() != null;}
}

三 客户端输入消息并发送

public class LoginClient {public static void main(String[] args) {//NioEventLoopGroup workerGroup = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap();bootstrap.group(workerGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel sc) throws Exception {sc.pipeline().addLast(new ClientHandler());}});connect(bootstrap,"127.0.0.1",8000,null);}private static void connect(Bootstrap bootstrap,String host,Integer port,Integer retry) {bootstrap.connect(host,port).addListener(future -> {System.out.println("future状态 :" + future.isSuccess());if (future.isSuccess()) {Channel channel = ((ChannelFuture) future).channel();startConsoleThread(channel);}});}private static void startConsoleThread(Channel channel) {new Thread(() -> {while (!Thread.interrupted()) {System.out.println("channel状态 :" + channel);if (LoginUtil.hasLogin(channel)) {System.out.println("输入消息发送至服务端 : ");Scanner sc = new Scanner(System.in);String line = sc.nextLine();MessageRequestPacket packet = new MessageRequestPacket();packet.setMessage(line);ByteBuf byteBuf = PacketCodeC.INSTANCE.encode(channel.alloc().ioBuffer(), packet);channel.writeAndFlush(byteBuf);}}}).start();}
}

四 服务端,客户端消息处理
服务端消息处理 :

if (packet instanceof MessageRequestPacket){MessageRequestPacket messageRequestPacket = (MessageRequestPacket) packet;System.out.println(new Date() + " : 收到客户端消息 : " + messageRequestPacket.getMessage());MessageResponsePacket responsePacket = new MessageResponsePacket();responsePacket.setMessage("服务端回复 : [ " + messageRequestPacket.getMessage() + " ] ");ByteBuf responseByteBuf = PacketCodeC.INSTANCE.encode(ctx.channel().alloc().ioBuffer(), responsePacket);ctx.channel().writeAndFlush(responseByteBuf);}

客户端消息处理 :

if (packet instanceof MessageResponsePacket) {MessageResponsePacket messageResponsePacket = (MessageResponsePacket) packet;System.out.println(new Date() + " : 收到服务端的消息 :" + messageResponsePacket.getMessage());}
总的来说流程也较为简单,并没有太复杂的处理,有什么问题的话,断点做下跟踪基本都能解决了

源码地址 : https://github.com/xiatiandao/Netty-IMServer/tree/master

Netty简单实现客户端与服务端收发消息相关推荐

  1. Netty实战 IM即时通讯系统(十)实现客户端和服务端收发消息

    Netty实战 IM即时通讯系统(十)实现客户端和服务端收发消息 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向通信 数据 ...

  2. java服务器向客户端发消息_java一个简单的客户端向服务端发送消息

    java一个简单的客户端向服务端发送消息 客户端代码: package com.chenghu.tcpip; import java.io.IOException; import java.io.Ou ...

  3. 【初识Netty使用Netty实现简单的客户端与服务端的通信操作Netty框架中一些重要的类以及方法的解析】

    一.Netty是什么? Netty 由 Trustin Lee(韩国,Line 公司)2004 年开发 本质:网络应用程序框架 实现:异步.事件驱动 特性:高性能.可维护.快速开发 用途:开发服务器和 ...

  4. 【Socket网络编程】4.tcp和udp的客户端和服务端收发流程

    tcp和udp的客户端和服务端收发流程 1.udp服务器流程: 1.创建serverSocket 2.设置服务器地址 serverAddr 3.将serverSocket和serverAddr绑定 b ...

  5. 简单的客户端,服务端通信

    client.c代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include ...

  6. Netty实战 IM即时通讯系统(十二)构建客户端与服务端pipeline

    Netty实战 IM即时通讯系统(十二)构建客户端与服务端pipeline 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向 ...

  7. Netty实战 IM即时通讯系统(六)实战: 客户端和服务端双向通信

    ## Netty实战 IM即时通讯系统(六)实战: 客户端和服务端双向通信 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 实战: 客户端和服务端双向通信 数据传输载 ...

  8. 带线程池的socket客户端与服务端

    前言 socket(套接字),Socket和ServerSocket位于java.net包中,之前虽然对socket有过一些了解,但一直都是云里雾里的,特意仔细的学习了一个socket,用socket ...

  9. Java--Socket客户端,服务端通信

    1.客户端接受服务端的消息并打印: 客户端: import java.io.BufferedReader; import java.io.IOException; import java.io.Inp ...

最新文章

  1. 三年级计算机课教案文档,小学三年级信息技术第十三课文件和文件夹教学设计...
  2. 【JUC并发编程09】读写锁
  3. hibernate教程--常用配置和核心API
  4. 中文语音情感识别python实现(一)
  5. python序列类型包括字符串_python序列类型字符串列表元组
  6. disBalancer(DDOS)将于4月15日在DuckSTARTER进行IDO
  7. 平面设计师必读的十本书
  8. Biztalk2009安装全过程截图,x64平台需要手动更改运行模式
  9. 2018 KDD CUP支付宝安全团队Deep X斩获两项大奖
  10. EMD、EEMD模态混叠、端点效应及改进研究(转)
  11. Unity3D中UGUI的RectTransform对齐方式详解
  12. java 文件拷贝保留原来的属性_Java常用属性拷贝工具类使用总结
  13. 国家二级计算机office知识点,2017年全国计算机二级office常见知识点
  14. systemctl enable与systemctl start的区别
  15. 土拍熔断意味着什么_315土拍将解地市之渴?“熔断”来了,别高兴太早
  16. 朱雀雀openfire+spark相关的中文资料
  17. 【echarts报错】[Vue warn]: Error in mounted hook (Promise/async): “TypeError: Cannot read properties of
  18. 微信小程序倒计时,购物车,向左滑删除 左拉删除
  19. 时间戳转换为yyyy-mm-dd hh:mm:ss格式
  20. uva10375 选择与除法 唯一分解定理

热门文章

  1. 马云卸任阿里巴巴CEO演讲全文:因为信任,所以简单!
  2. 搭建k8s的服务器硬件选型
  3. 车载注册蓝牙服务器,蓝牙配对码配备方法、系统、终端、服务器及车载设备专利_专利查询 - 天眼查...
  4. SpringBoot-starter-data整合Elasticsearch
  5. 坠落的唯品会与它焦虑的“二选一”
  6. 开放平台:网络淘金下一站
  7. 解决电脑浏览器突然无法打开网页
  8. 手把手教最新最全最详细Git使用教程(图文并茂,附Git命令大全学习文档)
  9. U8资产变动怎么处理
  10. 公允价值变动及公允价值变动损益