前言
像使用linux系统一样通过一个cmd窗口和朋友进行聊天是一件很炫酷的事情,同时也是规避公司聊天记录审查的一种手段,尤其一些公司禁止使用微信等聊天工具,这给日常同事们私下沟通交流增加了一些不便。
最终效果
使用netty实现自定义通信协议
1、定义消息加解密类
加密类
package pers.cz.netty.protocal;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.nio.charset.Charset;
/**
* @program: PostGirl-panent
* @description: 消息加密
* @author: Cheng Zhi
* @create: 2022-10-04 15:31
**/
public class TcpMessageEncoder extends MessageToByteEncoder<Message> {
private static final Logger log = LoggerFactory.getLogger(TcpMessageEncoder.class);
/*
+------------------------------------------------------------------------------------------------------------------------+
| 魔数 8byte 使用String描述 | 报文类型 1byte | attachments附件信息(长度不定) | 数据长度 8byte 使用long描述 |
+------------------------------------------------------------------------------------------------------------------------+
| 数据内容 (长度不定) |
+-------------------------------------------------------------------------------------------+
*/
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Message message, ByteBuf byteBuf) throws Exception {
// 写入魔数
byteBuf.writeBytes(ProtocalConst.POCKET_MAGIC_NUM.getBytes());
// 写入消息类型
byteBuf.writeByte(message.getMsgType().type());
// 写入附件信息
byteBuf.writeShort(message.getAttachments().size()); // 写入当前消息的附加参数数量
message.getAttachments().forEach((key, value) -> {
Charset charset = Charset.defaultCharset();
byteBuf.writeInt(key.length()); // 写入键的长度
byteBuf.writeCharSequence(key, charset); // 写入键数据
byteBuf.writeInt(value.length()); // 写入值的长度
byteBuf.writeCharSequence(value, charset); // 写入值数据
});
// 写入消息长度和数据内容
final Object content = message.getContent();
if (content == null) {
byteBuf.writeLong(0L);
} else {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(content);
byte[] bytes = bos.toByteArray();
byteBuf.writeLong(bytes.length);
// 主体消息
byteBuf.writeBytes(bytes);
}
}
}
加密类
package pers.cz.netty.protocal;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @program: PostGirl-panent
* @description: 消息解密
* @author: Cheng Zhi
* @create: 2022-10-04 15:30
**/
public class TcpMessageDecoder extends ByteToMessageDecoder {
private static final Logger log = LoggerFactory.getLogger(TcpMessageDecoder.class);
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf