小弟最近在做Socket通信程序,遇到Java中Read阻塞问题,一时想不到什么好的解决办法,恳请各位大侠指点一二,谢谢!具体问题如下:1、有什么办法能在读取Buffer时先知道Buffer里有多少字节的数据;
2、有什么办法不但能读到Buffer里的数据,而且还不会阻塞,不像read函数那样,当没有数据时就一直等待,直到有数据读出了才跳过;据说采用NIO可以解决以上问题,小弟看了看,由于时间紧迫,所以一时半会也没有看明白太多,没能解决。恳请各位大侠指点指点,深表感谢!
2、有什么办法不但能读到Buffer里的数据,而且还不会阻塞,不像read函数那样,当没有数据时就一直等待,直到有数据读出了才跳过;据说采用NIO可以解决以上问题,小弟看了看,由于时间紧迫,所以一时半会也没有看明白太多,没能解决。恳请各位大侠指点指点,深表感谢!
Buffer本来就是nio里的东西了
别为一个小问题制造更大的麻烦。
package com.soli.nio;import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
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 java.util.Set;public class ServerNIO {
public static void main(String[] args) throws Exception {
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
// ByteBuffer writeBuffer = ByteBuffer.wrap("服务器".getBytes());
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
writeBuffer.put("服务器".getBytes()); Selector selector = Selector.open(); InetSocketAddress address = new InetSocketAddress(9876); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(address);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("start"); while (true) {
int temp = selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
System.out.println("keys.size()=" + temp);
if (temp > 0) {
for (Iterator<SelectionKey> it = keys.iterator(); it.hasNext();) {
SelectionKey key = it.next();
System.out.println(key);
if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = ssc.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
while (true) {
readBuffer.clear();
int r = socketChannel.read(readBuffer);
System.out.println(r);
if (r <= 0) {
key.cancel();
socketChannel.close();
break;
}
System.out.println(new String(readBuffer.array()).trim());
// writeBuffer.flip();
// socketChannel.write(writeBuffer);
}
}
it.remove();
}
}
System.out.println("keys.size()=" + keys.size());
}
}
}
package com.soli.nio;import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class ClientNIO {
public static void main(String[] args) throws Exception {
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
writeBuffer.put("客户端".getBytes());
// ByteBuffer writeBuffer = ByteBuffer.wrap("客户端".getBytes());
ByteBuffer readBuffer = ByteBuffer.allocate(1024); Selector selector = Selector.open(); SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false); InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 9876);
System.out.println(socketChannel.connect(address)); while (!socketChannel.finishConnect())
;
// socketChannel.register(selector, SelectionKey.OP_READ); writeBuffer.flip();
socketChannel.write(writeBuffer);
// while (true) {
// int temp = selector.select();
// System.out.println(temp);
// if (temp > 0) {
// Set<SelectionKey> keys = selector.selectedKeys();
// for (Iterator<SelectionKey> it = keys.iterator(); it.hasNext();) {
// SelectionKey key = it.next();
// if (key.isReadable()) {
// System.out.println("ok");
// SocketChannel sc = (SocketChannel) key.channel();
// int r = sc.read(readBuffer);
// if (r <= 0) {
// break;
// }
// System.out.println(new String(readBuffer.array()).trim());
// }
// it.remove();
// }
// }
// }
}
}上面写得有点混乱,而且没带注析,带注析的那份在家请见量
SocketChannel socketChannel = (SocketChannel) key.channel();
while (true) {
readBuffer.clear();
int r = socketChannel.read(readBuffer);
System.out.println(r);
if (r <= 0) {
key.cancel();
socketChannel.close();
break;
}
System.out.println(new String(readBuffer.array()).trim());
// writeBuffer.flip();
// socketChannel.write(writeBuffer);
}
}但是第一次在 isReadable() 为 true 的时候,就进入了 while(true) 死循环了,如果有数据读的话还好,但是如果没有数据读取的话就会在 read 那里阻塞掉。另外,当 r < 0 的时候,表示客户端已经断开了连接,这时候才会退出。难道你的客户端用的是短连接?客户端要发消息时去连接一下,连完之后就断开了?
selector.selectedKeys这句其实是阻塞语句,所以就算没请求进来,也不会一直循环至于你说r<0的情况,那个只是测试一下而已,具体怎么写,要看需求
你服务端不用 socket.write(buffer) 的?
最多调用available方法,来探测一下,下一次不受阻塞能够读取到的字节数。
其他,未知。不知道,楼主要缓冲区的字节数干什么用 。