一.实现流程图
二.代码实现
-
整体结构图
-
utils/Attributes
public interface Attributes {
AttributeKey<Boolean> LOGIN = AttributeKey.newInstance("login");
}
public interface Command {
byte LOGIN_REQUEST = 1;
byte LOGIN_RESPONSE = 2;
byte MESSAGE_REQUEST = 3;
byte MESSAGE_RESPONSE = 4;
}
public class MyJsonSerializer implements MySerializer {
@Override
public byte[] serialize(Object object) {
return JSON.toJSONBytes(object);
}
@Override
public <T> T deserialize(Class<T> clazz, byte[] bytes) {
return JSON.parseObject(bytes, clazz);
}
}
public interface MySerializer {
byte[] serialize(Object object);
<T> T deserialize(Class<T> clazz, byte[] bytes);
}
public class PacketUtil {
public static ByteBuf encode(Packet packet) {
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer();
MySerializer serializer = SerializerFactory.getSerializer(packet.getSerMethod());
byte[] data = serializer.serialize(packet);
byteBuf.writeInt(packet.getMagic());
byteBuf.writeByte(packet.getVersion());
byteBuf.writeByte(packet.getSerMethod());
byteBuf.writeByte(packet.getCommand());
byteBuf.writeInt(data.length);
byteBuf.writeBytes(data);
return byteBuf;
}
public static Packet decode(ByteBuf byteBuf) {
byteBuf.skipBytes(4);
byteBuf.skipBytes(1);
byte serMethod = byteBuf.readByte();
byte command = byteBuf.readByte();
int length = byteBuf.readInt();
byte[] data = new byte[length];
byteBuf.readBytes(data);
Class<? extends Packet> packetType = getPacketType(command);
Packet res = SerializerFactory.getSerializer(serMethod).deserialize(packetType, data);
return res;
}
public static Class<? extends Packet> getPacketType(byte commond) {
if (commond == Command.LOGIN_REQUEST) {
return LoginRequestPacket.class;
}
if (commond == Command.LOGIN_RESPONSE) {
return LoginResponsePacket.class;
}
if (commond == Command.MESSAGE_REQUEST) {
return MessageRequestPacket.class;
}
if (commond == Command.MESSAGE_RESPONSE) {
return MessageResponsePacket.class;
}
return null;
}
}
public interface Serialize {
byte JSON = 1;
}
public class SerializerFactory {
public static MySerializer getSerializer(byte serName) {
if (serName == Serialize.JSON) {
return new MyJsonSerializer();
}
return null;
}
}
@Data
public abstract class Packet {
private int magic;
private byte version;
private byte serMethod;
private byte command;
}
- packet/MessageResponsePacket
@Data
public class MessageResponsePacket extends Packet {
private int magic = 20202020;
private byte version = 1;
private byte serMethod = Serialize.JSON;
private byte command = Command.MESSAGE_RESPONSE;
private String message;
@Override
public String toString() {
return "MessageRequestPacket{" +
"magic=" + magic +
", version=" + version +
", serMethod=" + serMethod +
", command=" + command +
", message='" + message + '\'' +
'}';
}
}
- packet/MessageRequestPacket
@Data
public class MessageRequestPacket extends Packet {
private int magic = 20202020;
private byte version = 1;
private byte serMethod = Serialize.JSON;
private byte command = Command.MESSAGE_REQUEST;
private String message;
@Override
public String toString() {
return "MessageRequestPacket{" +
"magic=" + magic +
", version=" + version +
", serMethod=" + serMethod +
", command=" + command +
", message='" + message + '\'' +
'}';
}
}
- packet/LoginResponsePacket
@Data
public class LoginResponsePacket extends Packet {
private int magic = 20202020;
private byte version = 1;
private byte serMethod = Serialize.JSON;
private byte command = Command.LOGIN_RESPONSE;
private boolean status;
private String message;
@Override
public String toString() {
return "LoginResponsePacket{" +
"magic=" + magic +
", version=" + version +
", serMethod=" + serMethod +
", command=" + command +
", loginStatus=" + status +
", message='" + message + '\'' +
'}';
}
}
- packet/LoginRequestPacket
@Data
public class LoginRequestPacket extends Packet {
private int magic = 20202020;
private byte version = 1;
private byte serMethod = Serialize.JSON;
private byte command = Command.LOGIN_REQUEST;
private long userId;
private String name;
private String password;
@Override
public String toString() {
return "LoginPacket{" +
"magic=" + magic +
", version=" + version +
", serMethod=" + serMethod +
", command=" + command +
", userId=" + userId +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class MyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf response = ByteBufAllocator.DEFAULT.ioBuffer();
Packet packet = PacketUtil.decode((ByteBuf) msg);
if (packet instanceof LoginRequestPacket) {
System.out.println("=====服务端接收到客户端登陆请求,正在校验=====");
LoginRequestPacket request = (LoginRequestPacket) packet;
LoginResponsePacket responsePacket = new LoginResponsePacket();
if (check(request)) {
System.out.println("登陆成功:"+request);
ctx.channel().attr(Attributes.LOGIN).set(true);
responsePacket.setStatus(true);
} else {
System.out.println("登陆失败:"+request);
responsePacket.setStatus(false);
}
response = PacketUtil.encode(responsePacket);
}
if (packet instanceof MessageRequestPacket) {
if (ctx.channel().attr(Attributes.LOGIN).get() == null) {
System.out.println("=====客户端尚未登陆,无法进行数据通信=====");
} else {
System.out.println("=====客户端登陆成功,进行数据通信=====");
MessageRequestPacket request = (MessageRequestPacket) packet;
System.out.println("收到:"+request.toString());
MessageResponsePacket responsePacket = new MessageResponsePacket();
responsePacket.setMessage("数据通信响应测试Reponse Test1");
response = PacketUtil.encode(responsePacket);
}
}
ctx.writeAndFlush(response);
}
private boolean check(LoginRequestPacket request) {
if ("ARong".equals(request.getName()) && "2020".equals(request.getPassword())) {
return true;
}
return false;
}
}
public class MyClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("=====客户端连接成功,尝试登陆=====");
Scanner input = new Scanner(System.in);
LoginRequestPacket packet = new LoginRequestPacket();
System.out.println("请输入登陆的用户ID");
packet.setUserId(Long.parseLong(input.nextLine()));
System.out.println("请输入登陆的用户账户");
packet.setName(input.nextLine());
System.out.println("请输入登陆的用户密码");
packet.setPassword(input.nextLine());
System.out.println("=====客户端开始发送登陆数据包=====");
ByteBuf request = PacketUtil.encode(packet);
ctx.writeAndFlush(request);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Packet packet = PacketUtil.decode((ByteBuf) msg);
if (packet instanceof LoginResponsePacket) {
LoginResponsePacket response = (LoginResponsePacket) packet;
if (response.isStatus()) {
System.out.println("=====客户端登陆成功=====");
} else {
System.out.println("=====客户端登陆失败=====");
}
MessageRequestPacket request = new MessageRequestPacket();
request.setMessage("数据通信请求测试Request Test1");
ByteBuf byteBuf = PacketUtil.encode(request);
ctx.writeAndFlush(byteBuf);
}
if (packet instanceof MessageResponsePacket) {
MessageResponsePacket request = (MessageResponsePacket) packet;
System.out.println("收到:"+request.toString());
}
}
}
public class NettyServer {
public static void main(String[] args) {
ServerBootstrap serverBootstrap = new ServerBootstrap();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(
new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new MyServerHandler());
}
}
).bind(8000);
}
}
public class NettyClient {
public static void main(String[] args) throws InterruptedException {
Bootstrap bootstrap = new Bootstrap();
NioEventLoopGroup group = new NioEventLoopGroup();
bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new MyClientHandler());
}
});
bootstrap.connect("127.0.0.1", 8000);
}
}