基于netty的可群聊聊天室

这篇博客详细介绍了如何基于Netty搭建一个支持群聊的聊天室,涉及环境配置如Java、Lombok、Gson和Logback。博主讲解了消息类的设计、序列化、通信协议、服务层实现,包括UserService和Session服务,以及服务器和客户端的处理器编写。此外,还提到了客户端的线程管理和RPC的初步实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.环境配置

<dependencies>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.39.Final</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>

 netty是本项目的基础

lombok用于简化开发

gson用于序列化Json

logback用于提供日志

二.包结构

其中message用于定义服务端和客户端的消息种类

protocol用于定义双方之间的通信协议

config用于从配置文件中读取配置

server包下,handler包用于定义处理各类request消息的处理器

service提供UserService服务,用于登录校验

session提供会话服务,包括私聊和群聊

三.开发message块

首先抽象出一个Message父类

public abstract class Message implements Serializable {
    protected int messageType;
    protected int messageSequenceId;
    public abstract int getMessageT();
    public abstract int getMessageSequenceId();

    public static final int LoginRequest=1;//登录请求
    public static final int LoginResponse=2;//登录响应
    public static final int ChatRequest=3;//私聊请求
    public static final int ChatResponse=4;//私聊响应
    public static final int GroupChatRequestMessage=5;//群聊请求
    public static final int GroupChatResponseMessage=6;//群聊响应
    public static final int GroupCreatRequestMessage=7;//创建group请求
    public static final int GroupCreatResponseMessage=8;//创建group响应
    public static final int GroupDetailsRequestMessage=9;//group细节请求
    public static final int GroupDetailsResponseMessage=10;//group细节响应
    public static final int GroupJoinRequestMessage=11;//加入group请求
    public static final int GroupJoinResponseMessage=12;//加入group响应
    public static final int GroupQuitRequestMessage=13;//退出group请求
    public static final int GroupQuitResponseMessage=14;//退出group响应
    public static final int PingMessage=15;//客户端心跳消息,之后3s一次
    public static final int RpcRequestMessage=101;//rpc请求消息
    public static final int RpcResponseMessage=102;//rpc请求响应
    public static HashMap<Integer,Class<?>> MessageMap=new HashMap<>();


    static {
        MessageMap.put(1,LoginRequestMessage.class);
        MessageMap.put(2,LoginResponseMessage.class);
        MessageMap.put(3,ChatRequestMessage.class);
        MessageMap.put(4,ChatResponseMessage.class);
        MessageMap.put(5,GroupChatRequestMessage.class);
        MessageMap.put(6,GroupChatResponseMessage.class);
        MessageMap.put(7,GroupCreatRequestMessage.class);
        MessageMap.put(8,GroupCreatResponseMessage.class);
        MessageMap.put(9,GroupDetailsRequestMessage.class);
        MessageMap.put(10,GroupDetailsResponseMessage.class);
        MessageMap.put(11,GroupJoinRequestMessage.class);
        MessageMap.put(12,GroupJoinResponseMessage.class);
        MessageMap.put(13,GroupQuitRequestMessage.class);
        MessageMap.put(14,GroupQuitResponseMessage.class);
        MessageMap.put(15,PingMessage.class);
        MessageMap.put(101, com.ghc.message.RpcRequestMessage.class);
        MessageMap.put(102, RpcResponseMessage.class);
    }
}

主要有两个字段: messageType消息类型,用于区分消息,messageSequenceId,提供一个通信序列号。将消息类型和其对应的Class类存入map,便于后续Gson反序列化使用

实现响应的子类,rpc相关消息最后实现

 为每个消息添加独有的字段,为了简单,暂时不考虑序列号

/**
 * 聊天
 */
@Data
public class ChatRequestMessage extends Message{
    private String source;
    private String target;
    private String content;

    public ChatRequestMessage(String source, String target, String content) {
        this.source = source;
        this.target = target;
        this.content = content;
    }

    @Override
    public int getMessageT() {
        return Message.ChatRequest;
    }

    @Override
    public int getMessageSequenceId() {
        return 0;
    }
}

其他的消息也一样,加入自己特有的字段

四.开发序列化器

为了增强可拓展性,让序列化器可选择,这里定义一个Serializer接口,提供反序列方法和序列方法。

public interface Serializer {

    //反序列化方法
    <T> T deserialize(Class<T> clazz,byte[] bytes);

    //序列化方法
    <T> byte[] serialize(T object);
}

接着在其内部用枚举的方式定义JDK序列化器和Gson序列化器(注意要实现Serializer接口)

enum Algorithm implements Serializer{

        Java{
            @Override
            public <T> T deserialize(Class<T> clazz, byte[] bytes) {
                try {
                    return (T) new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
                } catch (IOException | ClassNotFoundException e) {
                    throw ne
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值