Java 如何正确使用NIO选择器?
我在使用选择器时遇到问题 我编写了一些测试代码,尝试创建一个客户端/服务器连接,服务器端有一个选择器来管理通道。问题在于,当选择器选择要读取的通道并处理读取操作时,实际上不会读取任何数据 我把这个问题贴在了上,还没有收到任何答案 服务器:Java 如何正确使用NIO选择器?,java,networking,css-selectors,nio,Java,Networking,Css Selectors,Nio,我在使用选择器时遇到问题 我编写了一些测试代码,尝试创建一个客户端/服务器连接,服务器端有一个选择器来管理通道。问题在于,当选择器选择要读取的通道并处理读取操作时,实际上不会读取任何数据 我把这个问题贴在了上,还没有收到任何答案 服务器: static class Server implements Runnable { Selector sel; @Override public void run() { try { Serve
static class Server implements Runnable {
Selector sel;
@Override
public void run() {
try {
ServerSocketChannel server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(5555));
server.configureBlocking(false);
sel = Selector.open();
server.register(sel, SelectionKey.OP_ACCEPT);
boolean running = true;
while(running) {
int count = sel.select();
if(sel.isOpen() && count > 0) {
Set<SelectionKey> keyset = sel.selectedKeys();
synchronized(keyset) {
Iterator<SelectionKey> i = keyset.iterator();
while(i.hasNext()) {
SelectionKey key = i.next();
i.remove();
processKey(key);
}
}
} else if(!sel.isOpen())
running = false;
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void processKey(SelectionKey key) {
if(key.isValid() && key.isAcceptable()) {
try {
SocketChannel chan = ((ServerSocketChannel)key.channel()).accept();
chan.configureBlocking(false);
chan.register(sel, SelectionKey.OP_READ);
} catch (IOException e) {
e.printStackTrace();
}
}
if(key.isValid() && key.isReadable()) {
System.out.println("Read starting...");
SocketChannel chan = (SocketChannel) key.channel();
ByteBuffer buff = ByteBuffer.allocate(1024);
try {
while((chan.read(buff))>=0) {
buff.flip();
System.out.println("read some");
buff.clear();
}
chan.close();
System.out.println("Read complete");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
静态类服务器实现可运行{
选择器sel;
@凌驾
公开募捐{
试一试{
ServerSocketChannel服务器=ServerSocketChannel.open();
server.socket().bind(新的InetSocketAddress(5555));
server.configureBlocking(false);
sel=选择器.open();
服务器注册(sel,SelectionKey.OP_ACCEPT);
布尔运行=真;
(跑步时){
int count=sel.select();
如果(sel.isOpen()&&count>0){
Set keyset=sel.selectedKeys();
已同步(键集){
迭代器i=keyset.Iterator();
while(i.hasNext()){
SelectionKey=i.next();
i、 删除();
进程键(key);
}
}
}如果(!sel.isOpen())
运行=错误;
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
私有无效处理密钥(SelectionKey密钥){
if(key.isValid()&&key.isAcceptable()){
试一试{
SocketChannel=((ServerSocketChannel)key.channel()).accept();
chan.configureBlocking(假);
信道寄存器(sel,SelectionKey.OP_READ);
}捕获(IOE异常){
e、 printStackTrace();
}
}
if(key.isValid()&&key.isReadable()){
System.out.println(“读取开始…”);
SocketChannel=(SocketChannel)key.channel();
ByteBuffer buff=ByteBuffer.allocate(1024);
试一试{
而((chan.read(buff))>=0){
buff.flip();
System.out.println(“读取一些”);
buff.clear();
}
chan.close();
System.out.println(“读取完成”);
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
}
客户:
static class Client implements Runnable {
@Override
public void run() {
try {
SocketChannel chan = SocketChannel.open();
chan.connect(new InetSocketAddress("localhost", 5555));
while(!chan.finishConnect());
ByteBuffer buff = ByteBuffer.allocate(1024);
for(int i=0;i<1000;i++) {
buff.flip();
chan.write(buff);
buff.compact();
}
chan.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
静态类客户端实现可运行{
@凌驾
公开募捐{
试一试{
SocketChannel=SocketChannel.open();
connect(新的InetSocketAddress(“localhost”,5555));
而(!chan.finishConnect());
ByteBuffer buff=ByteBuffer.allocate(1024);
对于(inti=0;i来说,问题在于您的客户机,正如Tom所暗示的,它什么都不写。
下面是发生的情况:
ByteBuffer buff = ByteBuffer.alloacate(1024); // ==> position=0, limit=1024
然后:
这是在javdaoc for flip()中指定的:“将限制设置为当前位置,然后将位置设置为零”。
因此,您至少需要模拟将一些数据放入缓冲区,例如:
for(int i=0;i<1000;i++) {
buff.position(1024); // put 1024 bytes of data in the buffer
buff.flip();
...
}
for(inti=0;i问题出在您的客户机上,正如Tom所暗示的,它什么都不写。
下面是发生的情况:
ByteBuffer buff = ByteBuffer.alloacate(1024); // ==> position=0, limit=1024
然后:
这是在javdaoc for flip()中指定的:“将限制设置为当前位置,然后将位置设置为零”。
因此,您至少需要模拟将一些数据放入缓冲区,例如:
for(int i=0;i<1000;i++) {
buff.position(1024); // put 1024 bytes of data in the buffer
buff.flip();
...
}
for(int i=0;iIt看起来没有写入任何数据。(启动服务器和客户端之间也存在竞争。)我正在尝试写入空字节。它仍然应该写入数据,对吗?在启动客户端代码之前,我尝试使用Thread.sleep(),但没有任何帮助。但您从未填充缓冲区。调用limit(int)
应该这样做,我想。(免责声明:我已经十年没有真正做过任何合理的NIO编程了。)看起来你没有在写任何数据。(启动服务器和客户端之间也存在竞争。)我正在尝试写空字节。但它仍然应该写数据,对吗?我尝试使用Thread.sleep()在启动客户端代码之前,它没有任何帮助。但是您从未填充缓冲区。我认为,调用limit(int)
应该可以做到这一点。(免责声明:我实际上已经十年没有做任何合理的NIO编程了。)