Netty 同一個埠支援Tcp和 websocket
阿新 • • 發佈:2018-12-12
- 在Netty 實戰群裡討論了下能否一個埠支援tcp和websocket . 既然websocket是從http升級到websocket的 Netty能判斷http的話 理論上能判斷出是http的話,那就應該可以的。伺服器監聽埠,在最開始新增一個decode 這裡判斷是tcp還是http 來選擇新增對應的編解碼器。既然理論上行的通 ,那現在就開始驗證下吧。
- 伺服器端新增一個SelectDecode
package com.next.network; import com.next.network.tcp.DataObjectDecode; import com.next.network.tcp.DataObjectEncode; import com.next.network.tcp.NettyServerHandler; import com.next.network.websocket.LineParser; import com.next.network.websocket.WebSocketFrameHandler; import com.next.network.websocket.WebSocketIndexPageHandler; import com.next.server.Server; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; import io.netty.util.CharsetUtil; import io.netty.util.internal.AppendableCharSequence; import java.util.List; public class SelectDecode extends ByteToMessageDecoder { private final LineParser lineParser; public SelectDecode() { AppendableCharSequence seq = new AppendableCharSequence(128); lineParser = new LineParser(seq, 4096); } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { ChannelPipeline pipeline = ctx.channel().pipeline(); boolean skip = skipControlCharacters(in); List<ChannelHandler> list = null; //tcp if (!skip) { list = Server.getInstance().getTcpHandler(); } else { //http list = Server.getInstance().getWebsocketHandler(); } for (ChannelHandler ch : list) { pipeline.addLast(ch); } pipeline.remove(this); } private boolean skipControlCharacters(ByteBuf buffer) { buffer.markReaderIndex(); buffer.markWriterIndex(); boolean skiped = false; final int wIdx = buffer.writerIndex(); int rIdx = buffer.readerIndex(); while (wIdx > rIdx) { int c = buffer.getUnsignedByte(rIdx++); if (!Character.isISOControl(c) && !Character.isWhitespace(c)) { rIdx--; skiped = true; break; } } if (skiped) { AppendableCharSequence line = lineParser.parse(buffer); if (line == null) { skiped = false; } } buffer.readerIndex(rIdx); buffer.resetReaderIndex(); buffer.resetWriterIndex(); return skiped; } }
這裡面有一個關鍵方法 skipControlCharacters是從Netty的HttpObjectDecoder裡面copy過來稍微改了下
- 從判斷出來是http還是tcp來新增對應的編解碼,測試了下,是可以執行的(如果http判斷有誤的話 可以參考Netty的HttpObjectDecoder的程式碼多判斷些資料)。