Java 如何测试非阻塞通道的SocketChannel.read()是否已完成?
我正在使用一个函数从非阻塞SocketChannel(accept()的套接字)和阻塞SocketChannel(客户端)读取字节。我正在使用选择器实现一个服务器来处理多个客户端,并且我正在使用环回地址来仅使用我的笔记本电脑。这是我写的Java 如何测试非阻塞通道的SocketChannel.read()是否已完成?,java,sockets,nio,nonblocking,socketchannel,Java,Sockets,Nio,Nonblocking,Socketchannel,我正在使用一个函数从非阻塞SocketChannel(accept()的套接字)和阻塞SocketChannel(客户端)读取字节。我正在使用选择器实现一个服务器来处理多个客户端,并且我正在使用环回地址来仅使用我的笔记本电脑。这是我写的 while((r = socketChannel.read(ackBuf)) != -1) { System.out.println(name3d+" r: "+r); } 我希望当到达频道内容的末尾时,read()会返回-1,但不是成
while((r = socketChannel.read(ackBuf)) != -1) {
System.out.println(name3d+" r: "+r);
}
我希望当到达频道内容的末尾时,read()会返回-1,但不是成功的结果。
read(),在非阻塞配置中,如果此时还没有准备好读取的内容,则返回0,但如果我将代码更改为
while((r = socketChannel.read(ackBuf)) > 0) {
System.out.println(name3d+" r: "+r);
}
如果稍后有东西准备好,我也不会什么都不看。
如何区分我得到0是因为未准备好还是因为它已结束?
在下面的代码片段中,我可以在睡眠后再次测试读取,但我确信这不是我想要的可靠方法
int times = 0;
while((r = socketChannel.read(ackBuf)) != -1 && times<2) {
if (r == 0)
try {
Thread.sleep(500);
times++;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name3d+" r: "+r);
}
int次=0;
while((r=socketChannel.read(ackBuf))!=-1&ד如果我得到0是因为没有准备好还是因为它结束了?”你是指消息还是整个通信
对于消息,您应该使用通信协议(如json或http)进行通信,我认为您应该得到一个SocketException…如果您使用阻塞,另一端的人关闭了连接,您会得到…(我已经写信给很多人,告诉他们SocketException是您的朋友)
---编辑---
查看通道的文档,如果/当通道关闭时,您应该会得到某种IOException(SocketException是IOException的子类)。如果“我得到0是因为未准备好还是因为它已结束?”您是指消息还是通信的全部
对于消息,您应该使用通信协议(如json或http)进行通信,我认为您应该得到一个SocketException…如果您使用阻塞,另一端的人关闭了连接,您会得到…(我已经写信给很多人,告诉他们SocketException是您的朋友)
---编辑---
查看通道的文档,如果/当通道关闭时,使用的非阻塞SocketChannel有点不同,那么您应该会得到某种类型的IOException(SocketException是IOException的子类)
首先等待选择键告诉您有数据,然后
然后从通道读取数据
参见本规范草案:
Selector selector = Selector.open();
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(addr);
sc.register(selector, SelectionKey.OP_READ);
while (true) {
// select() can block!
if (selector.select() == 0) {
continue;
}
Iterator iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = (SelectionKey) iterator.next();
iterator.remove();
if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer bb = ByteBuffer.allocate(1024);
sc.read(bb);
System.out.println("Message received!");
}
}
使用的非阻塞SocketChannel有点不同
首先等待选择键告诉您有数据,然后
然后从通道读取数据
参见本规范草案:
Selector selector = Selector.open();
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(addr);
sc.register(selector, SelectionKey.OP_READ);
while (true) {
// select() can block!
if (selector.select() == 0) {
continue;
}
Iterator iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = (SelectionKey) iterator.next();
iterator.remove();
if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer bb = ByteBuffer.allocate(1024);
sc.read(bb);
System.out.println("Message received!");
}
}
因此,如果选择了socketChannel的键,我将永远不会得到0!这解释了所有问题。谢谢:)以防御方式发言,不一定。但大多数情况下,您都有机会获得超过0的分数。:-)因此,如果选择了socketChannel的键,我将永远不会得到0!这就解释了一切。谢谢:)用防御的语气说,不一定。但大多数情况下,您都有机会获得超过0的分数。:-)我在谈论这个消息。我使用自己的协议,在客户端设置与服务器的TCP通信后,客户端通过socketchannel发送一些字节,第一个字节用于标识特定请求,以便服务器了解客户端请求的类型。以类似的方式,服务器向clientI发送字节,我正在谈论该消息。我使用自己的协议,在客户端设置与服务器的TCP通信后,客户端通过socketchannel发送一些字节,第一个字节用于标识特定请求,以便服务器了解客户端请求的类型。服务器以类似的方式向客户端发送字节