首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Socket 服務端:基於協議解析器的多業務請求分發與主動推送架構

     編輯:程式設計綜合問答

核心痛點

單一 `readLine()` 循環無法區分「語音/視頻/圖片/數據」等異構請求,且無法實現服務端主動推送。

解決方案:自定義應用層協議 + Netty 框架


// 1. 協議定義 (JSON 示例)
{
  "cmd": "LOGIN",           // 命令字
  "seq": 1001,              // 請求序列號
  "payload": { ... }        // 業務負載
}

Netty 架構分層

層級組件職責
傳輸層NioEventLoopGroup網絡 I/O 事件循環
協議層LengthFieldBasedFrameDecoder + JsonDecoder/Encoder半包/粘包處理、序列化
業務層CommandHandler 命令分發器根據 cmd 路由到具體 Handler
會話層ChannelGroup / AttributeKey管理在線用戶、群組、心跳

關鍵代碼骨架


// 命令分發器
public class CommandDispatcher extends SimpleChannelInboundHandler {
    private final Map handlers = new ConcurrentHashMap<>();

    public void register(String cmd, CommandHandler handler) {
        handlers.put(cmd, handler);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ProtocolMessage msg) {
        CommandHandler handler = handlers.get(msg.getCmd());
        if (handler != null) {
            handler.handle(ctx, msg);
        } else {
            log.warn("未知命令: {}", msg.getCmd());
        }
    }
}

// 具體業務 Handler
public class VoiceHandler implements CommandHandler {
    @Override
    public void handle(ChannelHandlerContext ctx, ProtocolMessage msg) {
        // 處理語音幀,轉發給目標用戶/群組
        SessionManager.forwardToGroup(msg.getGroupId(), msg);
    }
}

// 主動推送:服務端任意位置調用
public class NotificationService {
    public void pushLocationUpdate(String groupId, Location loc) {
        ProtocolMessage msg = ProtocolMessage.builder()
            .cmd("LOCATION_UPDATE")
            .payload(loc)
            .build();
        SessionManager.getGroupChannels(groupId).writeAndFlush(msg);
    }
}

為什麼不建議原生 Socket + 手寫協議?

  • 半包/粘包處理極易出 Bug。
  • 線程模型難以支撐高併發 (C10K 問題)。
  • SSL/TLS、WebSocket 升級、流控、重連需自行實現。
  • Netty/Mina/gRPC 已解決以上所有問題,生產級穩定。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved