Я изучаю книгу Pro Java 7 NIO.2
, чтобы лучше понять пакет NIO и хотел бы работать над некоторым сетевым кодом, чтобы лучше понять, как работает netty в фоновом режиме. Общая ошибка имеет смысл, но причина, по которой возникает ошибка, выходит за рамки моего понимания.CastException с сокетами Java NIO
java.lang.ClassCastException: sun.nio.ch.ServerSocketChannelImpl cannot be cast to java.nio.channels.SocketChannel
Первое, что я сделал, чтобы убедиться, что ни один из моего кода не импортируя ничего из упаковки солнца, и что все, что было в самом деле, с помощью пакета java.nio. Все, кажется, проверяет.
Эта ошибка возникает при попытки подключения клиента к серверу, но то, что действительно беспокоит меня это вообще то, что он пытается типовой отливку к ServerSocketChannel, а не просто SocketChannel, что приводит меня к что Сервер запутан.
Я заранее извиняюсь за стену кода внизу, но так как каждый всегда просит, чтобы я опубликовал пример выполнения, я планирую сделать именно это. Это три файла классов.
TcpProcessor.java
package net.ogserver.proto.tcp;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import net.ogserver.proto.connections.Connection;
public class TcpProcessor implements Runnable {
public static int tcpPort;
public void run() {
try (Selector selector = Selector.open();
ServerSocketChannel serverSocket = ServerSocketChannel.open()) {
if((serverSocket.isOpen()) && (selector.isOpen())) {
serverSocket.configureBlocking(false);
serverSocket.bind(new InetSocketAddress(tcpPort));
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server has started and is waiting for connections...");
while(!Thread.interrupted()) {
selector.select();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while(keys.hasNext()) {
SelectionKey key = (SelectionKey) keys.next();
keys.remove();
if(!key.isValid()) {
continue;
}
if(key.isAcceptable()) {
processIncomingConnection(key, selector);
} else if(key.isReadable()) {
//processIncomingData(key);
} else if(key.isWritable()) {
//pushOutgoingData(key);
}
}
}
} else {
System.err.println("There was an issue constructing the socket.");
}
} catch(IOException e) {
e.printStackTrace();
}
}
private void processIncomingConnection(SelectionKey selectionKey, Selector selector) throws IOException {
ServerSocketChannel serverSocket = (ServerSocketChannel)selectionKey.channel();
SocketChannel clientSocket = serverSocket.accept();
clientSocket.configureBlocking(false);
System.out.println("Incoming connection from " + clientSocket.getRemoteAddress());
selectionKey.attach(new Connection(selectionKey));
clientSocket.register(selector, SelectionKey.OP_READ);
}
}
Connection.java
package net.ogserver.proto.connections;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
public class Connection {
private SelectionKey selectionKey;
private SocketChannel clientSocket;
private ByteBuffer networkInputBuffer;
private ByteBuffer networkOutputBuffer;
public Connection(SelectionKey selectionKey) {
this.selectionKey = selectionKey;
this.clientSocket = (SocketChannel)selectionKey.channel();
this.networkInputBuffer = ByteBuffer.allocate(1024);
this.networkOutputBuffer = ByteBuffer.allocate(8192);
}
public SelectionKey getSelectionKey() {
return selectionKey;
}
public ByteBuffer getInputBuffer() {
return networkInputBuffer;
}
public ByteBuffer getOutputBuffer() {
return networkOutputBuffer;
}
public SocketChannel getChannel() {
return clientSocket;
}
}
Server.java
package net.ogserver.proto;
import net.ogserver.proto.tcp.TcpProcessor;
public class Server {
private Thread tcpProcessor;
public Server(int port) {
TcpProcessor.tcpPort = port;
tcpProcessor = new Thread(new TcpProcessor());
tcpProcessor.start();
}
public static void main(String[] args) {
new Server(5055);
}
}
Там заблуждаться или возникает, когда вызывается TcpProcessor#processIncomingConnection
, который вызывает создание нового экземпляра Connection
. Линия, бросающая эту ошибку, - это прямая цитата из книги, и я взглянул на несколько других серверов NIO, и в большинстве случаев строка имеет одно и то же значение (Minus some names).
this.clientSocket = (SocketChannel)selectionKey.channel();
Любая помощь будет высоко оценена, полный консольный вывод для тех, кто хочет это:
Server has started and is waiting for connections...
Incoming connection from /127.0.0.1:53221
Exception in thread "Thread-0" java.lang.ClassCastException: sun.nio.ch.ServerSocketChannelImpl cannot be cast to java.nio.channels.SocketChannel
at net.ogserver.proto.connections.Connection.<init>(Connection.java:17)
at net.ogserver.proto.tcp.TcpProcessor.processIncomingConnection(TcpProcessor.java:60)
at net.ogserver.proto.tcp.TcpProcessor.run(TcpProcessor.java:37)
at java.lang.Thread.run(Thread.java:745)
Я, вероятно, следует добавить, что реализация типажей SocketChannel образуют selectionkey.channel() приходит прямо из JavaDocs - http://www.onjava.com/pub/a/onjava/2002/09/04/nio.html?page=2
Посмотрите на источник sun.nio.ch.ServerSocketChannelImpl, он, кажется, расширяет java.nio.channels.ServerSocketChannel и реализует sun.nio.ch.SelChImpl, но, похоже, нет связи с java.nio.channels .SocketChannel – hammerfest
@hammerfest - Самая странная проблема и самый ошеломляющий из всех заключается в том, что это происходит только при локальном подключении клиента. (Этот клиент находится на том же компьютере, что и сервер) – Hobbyist