- 在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的代码多判断些数据)。
- 代码链接地址