Open stoneLee81 opened 4 years ago
下面的代码导致了你这个错误 com.corundumstudio.socketio.protocol.PacketDecoder#readNamespace
private String readNamespace(ByteBuf frame){
/**
* namespace post request with url queryString, like
* /message?a=1,
* /message,
*/
int endIndex = frame.bytesBefore((byte)'?');
if(endIndex > 0){
return readString(frame,endIndex);
}
endIndex = frame.bytesBefore((byte)',');
if(endIndex > 0){
return readString(frame,endIndex);
}
return readString(frame);
}
当你的namespace包含queryString时,它会只会读取问号前面的部分,不会处理问号后面的部分。
例如:
io.connect(domain+"/im/user?appid=clientid&userid=userid“, {"transports": ["websocket"]});
这段代码将会产生一个websocket连接,并且在连接建立成功后client会发送一个数据包到server端, 这个数据包的内容将会是这样的:
40/im/user?appid=clientid&userid=userid
这个数据包分为三部分:
第一部分:4
第一位为主类型,OPEN(0), CLOSE(1), PING(2), PONG(3), MESSAGE(4), UPGRADE(5), NOOP(6)
第二部分:0
第二位为次类型,CONNECT(0, true), DISCONNECT(1, true), EVENT(2, true), ACK(3, true), ERROR(4, true), BINARY_EVENT(5, true), BINARY_ACK(6, true)
第三部分: /im/user?appid=clientid&userid=userid
表示data
服务端在接收到这段数据包后,通过while循环来逐个字节解析数据包PacketDecoder#readNamespace这个方法将会从这段数据包中解析出namespace,这个方法的参数的内容为:/im/user?appid=clientid&userid=userid
,对于这个参数,该方法只读取了/im/user
这几个字符,导致frame
参数里面的内容还剩下?appid=clientid&userid=userid
没有处理,而这个frame
则来源于InPacketHandler
类中的channelRead0
方法,代码如下
@Override
protected void channelRead0(io.netty.channel.ChannelHandlerContext ctx, PacketsMessage message)
throws Exception {
ByteBuf content = message.getContent();
ClientHead client = message.getClient();
if (log.isTraceEnabled()) {
log.trace("In message: {} sessionId: {}", content.toString(CharsetUtil.UTF_8), client.getSessionId());
}
while (content.isReadable()) {
try {
Packet packet = decoder.decodePackets(content, client);// frame 来源于这里的 content
......
}
当frame
里面还剩有?appid=clientid&userid=userid
这部分内容时,content.isReadable()
的值为 true
,那么while循环体就会继续执行,最终它会执行到 com.corundumstudio.socketio.protocol.PacketDecoder#readType
这个方法
private PacketType readType(ByteBuf buffer) { //buffer=?appid=clientid&userid=userid
int typeId = buffer.readByte() & 0xF;
return PacketType.valueOf(typeId);
}
buffer.readByte()
表示读取一个字节,这里是?
在ascii码表中,?=63。所以,typeId = 63 & 0xF = 15。
再看下PacketType.valueOf
方法:
public static PacketType valueOf(int value) { // value=15
for (PacketType type : VALUES) {
if (type.getValue() == value && !type.inner) {
return type;
}
}
throw new IllegalStateException();
}
public enum PacketType {
OPEN(0), CLOSE(1), PING(2), PONG(3), MESSAGE(4), UPGRADE(5), NOOP(6),
CONNECT(0, true), DISCONNECT(1, true), EVENT(2, true), ACK(3, true), ERROR(4, true), BINARY_EVENT(5, true), BINARY_ACK(6, true);
......
所以在PacketType.valueOf
方法中符合条件的值是:0,1,2,3,4,5,6
,而我们这里是15,自然就会抛出IllegalStateException
异常,也就是你所看到的异常。
修改readNamespace
源码
private String readNamespace(ByteBuf frame) {
/*********************** modify start *************************************/
ByteBuf buffer = frame.slice();
// skip this frame
frame.readerIndex(frame.readerIndex() + frame.readableBytes());
/*********************** modify end *************************************/
/**
* namespace post request with url queryString, like
* /message?a=1,
* /message,
*/
int endIndex = buffer.bytesBefore((byte) '?');
if (endIndex > 0) {
return readString(buffer, endIndex);
}
endIndex = buffer.bytesBefore((byte) ',');
if (endIndex > 0) {
return readString(buffer, endIndex);
}
return readString(buffer);
}
放弃使用 namespace
非常感谢,用你的方法解决了这个问题
pretty nice
@DoubleDD 我去修改源码,但是发现有点难扩展。有没有具体的修改的方式。1.7.18
@DoubleDD 我去修改源码,但是发现有点难扩展。有没有具体的修改的方式。1.7.18
解决方案一里面的代码贴过去就能用,但是不知道你说的扩展是指的什么,我这边解决这个问题的时候目标很明确,就是要干掉那个报错,并没有做其他的扩展,如果要扩展的话还要看下具体的需求而定。
@DoubleDD 我去修改源码,但是发现有点难扩展。有没有具体的修改的方式。1.7.18
解决方案一里面的代码贴过去就能用,但是不知道你说的扩展是指的什么,我这边解决这个问题的时候目标很明确,就是要干掉那个报错,并没有做其他的扩展,如果要扩展的话还要看下具体的需求而定。
@DoubleDD 嗯嗯, 我这边已解决了。感谢
When I was using websocket transport to connect netty-socket server side, it seems to have bug, below is my demo code and excpeitons:
js code: io.connect(domain+"/im/user?appid="+clientid+"&userid="+userid+"&invitation=Y&ipaddr="+ipaddr+"&referer="+referer+"&userAgent="+SIP.Utils.getUserAgent(), {"transports": ["websocket"]});
threw below exception: java.lang.IllegalStateException: null at com.corundumstudio.socketio.protocol.PacketType.valueOf(PacketType.java:48) ~[netty-socketio-1.7.17.jar:?] at com.corundumstudio.socketio.protocol.PacketDecoder.readType(PacketDecoder.java:86) ~[netty-socketio-1.7.17.jar:?] at com.corundumstudio.socketio.protocol.PacketDecoder.decode(PacketDecoder.java:160) ~[netty-socketio-1.7.17.jar:?] at com.corundumstudio.socketio.protocol.PacketDecoder.decodePackets(PacketDecoder.java:142) ~[netty-socketio-1.7.17.jar:?] at com.corundumstudio.socketio.handler.InPacketHandler.channelRead0(InPacketHandler.java:65) [netty-socketio-1.7.17.jar:?] at com.corundumstudio.socketio.handler.InPacketHandler.channelRead0(InPacketHandler.java:36) [netty-socketio-1.7.17.jar:?] at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:301) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) [netty-all-4.1.32.Final.jar:4.1.32.Final] at com.corundumstudio.socketio.transport.WebSocketTransport.channelRead(WebSocketTransport.java:95) [netty-socketio-1.7.17.jar:?] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at com.corundumstudio.socketio.transport.PollingTransport.channelRead(PollingTransport.java:109) [netty-socketio-1.7.17.jar:?] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at com.corundumstudio.socketio.handler.AuthorizeHandler.channelRead(AuthorizeHandler.java:137) [netty-socketio-1.7.17.jar:?] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:108) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:656) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:591) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:508) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:470) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909) [netty-all-4.1.32.Final.jar:4.1.32.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-all-4.1.32.Final.jar:4.1.32.Final] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]