- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试将我的网络从标准 IO 转移到 NIO,并遵循一些试图解决这个问题的教程,而我、我自己和我认为花我的时间是一个好主意。第一周重写所有应用程序逻辑处理的核心,我从来没有想到我无法建立基本的网络。
目前网络处于非常基本的阶段,所有内容都被扔进 while 循环中,考虑到我没有任何线索,我不能诚实地说我已经尝试过让它看起来不错我正在做的事情是我的目标是首先弄清楚如何去做,然后回去进行改造。
这是我用来初始化服务器的代码:
// Initializes the TCP Server and all of its components.
private void initTcpServer(int port) {
try {
// Create a new selector
Selector socketSelector = SelectorProvider.provider()
.openSelector();
// Create a new non-blocking server socket channel;
this.serverSocketChannel = ServerSocketChannel.open();
this.serverSocketChannel.configureBlocking(false);
// Bind the server socket to the specified address and port
this.serverSocketChannel.socket().bind(
new InetSocketAddress("127.0.0.1", port));
// Register the server socket channel, indicating an interest in
// accepting new connections
this.serverSocketChannel.register(socketSelector,
SelectionKey.OP_ACCEPT);
// Set the selector for the server instance.
this.selector = socketSelector;
} catch (IOException e) {
e.printStackTrace();
}
}
然后该类实现了Runnable接口(interface),该方法完成后直接启动一个新的线程,在该线程中我们包含以下代码:
public void run() {
while (isRunning) {
try {
selector.selectNow();
} catch (IOException io) {
return;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (!key.isValid()) {
it.remove();
continue;
}
try {
if (key.isAcceptable()) {
this.handleConnection(key);
} else if (key.isReadable()) {
Connection connection = (Connection) key.attachment();
if (connection != null) {
try {
connection.getMasterProtocol()
.decode(connection,
connection.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
} finally {
it.remove();
}
}
}
}
根据我的理解,这使我们能够基于 SelectionKey
处理我们的连接和数据..并且是所有基于 NIO 的网络运行的基础,你会看到我我正在调用两个不同的方法来避免那么困惑,第一个是#handleConnection
,另一个是解码函数。
句柄连接方法创建我的 Connection
类的新实例并将其附加到 SelectionKey,如下所示:
public Connection(SelectionKey key) {
try {
// For an accept to be pending the channel must be a server socket channel.
ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel();
// Accept the connection and make it non-blocking.
this.socketChannel = serverSocketChannel.accept();
this.socketChannel.configureBlocking(false);
// Set up other user data.
this.inputStream = new DataInputStream(socketChannel.socket().getInputStream());
this.masterProtocol = new MasterProtocol();
// Register the new SocketChannel with our Selector, indicating
// we'd like to be notified when there's data waiting to be read.
key = this.socketChannel.register(OGServer.getInstance().getSelector(), SelectionKey.OP_READ);
key.attach(this);
// Add the current <SelectorKey, Connection> to the current connections collection.
connections.put(key, this);
Log.debug(getClass(), "Connection constructed successfully.");
} catch(IOException e) {
e.printStackTrace();
}
}
当我尝试调用 MasterProtocol#decode
方法时,会调用该错误,如下所示:
public Object decode(Connection connection, DataInputStream dataInputStream) throws IOException {
if(connection.getState() == ConnectionState.CONNECTED) {
byte[] bytes = ByteStreams.toByteArray(dataInputStream);
if(bytes.length < 4) {
System.out.println("Not enough bytes read.");
return null;
}
int bufferSize = dataInputStream.readInt();
System.out.println("Buffer Size: " + bufferSize);
while(bytes.length < bufferSize) {
return null;
}
int test = dataInputStream.readInt();
System.out.println("Test: " + test);
return null;
}
return null;
}
当DataInputStream
尝试从网络读取时,似乎会调用该错误,更具体地说是在这行代码上:
byte[] bytes = ByteStreams.toByteArray(dataInputStream);
错误:
Exception in thread "Thread-0" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.SocketAdaptor$SocketInputStream.read(SocketAdaptor.java:190)
at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:103)
at java.io.DataInputStream.read(DataInputStream.java:100)
at com.google.common.io.ByteStreams.copy(ByteStreams.java:70)
at com.google.common.io.ByteStreams.toByteArray(ByteStreams.java:115)
at net.ogserver.framework.net.protocol.MasterProtocol.decode(MasterProtocol.java:29)
at net.ogserver.framework.net.OGServer.run(OGServer.java:146)
at java.lang.Thread.run(Thread.java:745)
“IllegalBlockingModeException”异常让我感到困惑,因为我找到的所有信息都是用于设置非阻塞服务器的,但 DataInputStream 实现是我自己的,所以我一定在某个地方做错了。 NIO 和 IO 是完全不同的世界,但是学习就是学习,嗯?
编辑:我想这有助于了解我如何从客户端发送数据,这只是一个非常基本的测试应用程序,可以执行此操作:
socket = new Socket("127.0.0.1", 5055);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeBoolean(false);
最佳答案
如果您要以非阻塞方式迁移到 NIO,则无法继续使用流。如果你想使用流,那么使用 NIO 根本没有任何优势。我现在就停止迁移项目。
关于java - 从 IO 迁移到 NIO - 网络、IllegalBlockingModeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27196991/
我是 NIO 的新手,正在构建一个聊天应用程序,我在所有客户端都建立了连接,但是在从客户端读取内容时,我遇到了 java.nio.channels.IllegalBlockingModeExcepti
我正在尝试将我的网络从标准 IO 转移到 NIO,并遵循一些试图解决这个问题的教程,而我、我自己和我认为花我的时间是一个好主意。第一周重写所有应用程序逻辑处理的核心,我从来没有想到我无法建立基本的网络
我正在尝试开发一个连接到 mPos 设备并能够成功付款的 Android 应用程序。第一步,我尝试通过蓝牙进行连接,并且已成功将智能手机与mPos,但是当我尝试获取从设备生产商提供的 API 返回的终
当我这样写代码时: ServerSocketChannel ssc = ServerSocketChannel.open(); InetSocketAddress sa = new InetSocke
我是一名优秀的程序员,十分优秀!