Java Nio服务器中的CasteException:无法将SocketChannel强制转换为ServerSocketChannel
我首先使用伪代码来描述这个问题,然后将整个代码粘贴到下面的代码中,它可以在本地运行Java Nio服务器中的CasteException:无法将SocketChannel强制转换为ServerSocketChannel,java,nio,classcastexception,Java,Nio,Classcastexception,我首先使用伪代码来描述这个问题,然后将整个代码粘贴到下面的代码中,它可以在本地运行 1.selector = Selector.open(); serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); serverChannel.socket().bind(new InetSocketAddress(port), 1024); serverChannel.register
1.selector = Selector.open();
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress(port), 1024);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
2.while(true){
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
3. if(!key.isAcceptable()){
continue;
}
4. ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
...
}
}
异常发生在步骤4中,然后我在步骤3中进行检查,但它无法通过可接受的检查并进入死循环。
有时候,它可以正常接收和响应,我没有做任何改变,这对我来说太奇怪了。
在这里我粘贴代码,希望有人能帮助我。谢谢
包io.Nio;
导入java.io.IOException;
导入java.net.InetSocketAddress;
导入java.nio.ByteBuffer;
导入java.nio.channels.ClosedSelectorException;
导入java.nio.channels.SelectionKey;
导入java.nio.channels.Selector;
导入java.nio.channels.ServerSocketChannel;
导入java.nio.channels.SocketChannel;
导入java.util.Iterator;
导入java.util.Set;
导入io.util.IOUtil;
公共类NioServer扩展线程{
专用int端口;
专用选择器;
专用服务器socketchannel服务器通道;
公共NioServerint端口{
this.port=端口;
}
@凌驾
公开募捐{
试一试{
选择器=selector.open;
serverChannel=ServerSocketChannel.open;
serverChannel.configureBlockingfalse;
serverChannel.socket.bindnew-InetSocketAddressport,1024;
serverChannel.registerselector,选择key.OP_ACCEPT;
}卡奇奥例外{
IOUtil.closeserverChannel;
}
System.out.printlnserver启动:+端口;
whiletrue{
试一试{
selector.select;
}捕获关闭的选择异常e{
e、 打印跟踪;
}捕捉异常{
e、 打印跟踪;
}
设置键=选择器。选择键;
迭代器it=keys.Iterator;
当它有下一个{
选择key=it.next;
如果!key.isValid{
键。取消;
IOUtil.closekey.channel;
IOUtil.closekey.selector;
System.out.printlnIOUtil.now+清除无效密钥。;
持续
}
//我在这里做了一个检查,如果不可接受,那么继续,但这是一个死循环
如果!key.isAcceptable{
System.out.PrintLn不可接受;
持续
}
试一试{
//此处的例外情况:无法将SocketChannel强制转换为服务器SocketChannel
ServerSocketChannel serverChannel=ServerSocketChannel key.channel;
SocketChannel通道=serverChannel.accept;
ifchannel==null{
持续
}
channel.configureBlockingfalse;
channel.registerselector,选择key.OP_READ;
//如果key.isReadable{
//System.out.PrintLn未读取;
// }
ByteBuffer缓冲区=ByteBuffer.allocate1024;
如果channel.readbuffer>0{
buffer.flip;
byte[]byteArray=新字节[缓冲区剩余];
buffer.getbyteArray;
字符串表达式=新StringbyteArray,UTF-8;
System.out.printlnIOUtil.now+接收请求:+表达式;
字符串结果=null;
响应通道、结果;
}
}捕捉异常{
e、 打印跟踪;
}
}
}
}
公共空间关闭{
IOUtil.closeselector;
IOUtil.closeserverChannel;
}
private void ResponseCheckChannel通道,字符串响应引发IOException{
回复=你好回复;
System.out.printlnIOUtil.now+发送响应:+响应;
字节[]字节=response.getBytes;
ByteBuffer缓冲区=ByteBuffer.allocatebytes.length;
buffer.putbytes;
buffer.flip;
channel.writebuffer;
}
公共静态无效字符串[]args{
新的NioServerIOUtil.DEFAULT\u PORT.start;
}
} 您描述的异常可能发生的唯一方式是,如果您在非ServerSocketChannel的通道上尝试该类型转换,如果其密钥已准备就绪但“不可接受”,则可能发生这种情况。很明显,当您遇到此异常时,您没有步骤2,因此您处理了一个“可读”通道,就好像它是一个“可接受”通道一样 因此,您发布的代码实际上并没有显示出这个问题,但它确实存在大量其他问题。您不需要仅仅因为某个键无效就关闭选择器,如果该键无效,则该键已被取消,因此您不需要取消该键,而且关闭通道会取消该键。为什么您对接受并注册OP_READ频道的OP_READ/isReadable不感兴趣?为什么你不等待OP_read就试图从你刚刚接受的频道阅读 扔掉它,好好看看JavaNIO教程 我确实想评论一下客户中的一条胡说八道:
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress(ip,port));
while(!socketChannel.finishConnect()){
yield();
}
在这里,您正在以非阻塞模式执行阻塞模式连接的等效操作。它可以全部替换为:
socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress(ip,port));
socketChannel.configureBlocking(false);
然后:
在这里,您正在注册一个已经发生的事件。真奇怪。您将永远无法从已连接的套接字获得OP_CONNECT。移除。从未见过这种情况。您不需要仅仅因为某个键无效就关闭选择器,如果该键无效,则该键已被取消,因此您不需要取消该键,而且关闭通道会取消该键。这里的代码很奇怪。为什么是ar
你对接受并注册OP_READ频道的OP_READ不感兴趣吗?为什么你不等待OP_read就试图从你刚刚接受的频道阅读?当你准备从频道上阅读时,为什么你不打印而阅读呢?我建议您好好看看NIO教程。此代码是垃圾。您也在错误的键上调用key.isReadable。无法复制。很明显,这不是真正的代码。对不起,我错了。我已经把它藏起来了。
socketChannel.register(selector, SelectionKey.OP_CONNECT);