简体   繁体   English

Java NIO选择器.select()始终仅为OP_ACCEPT SelectionKey返回一个SelectionKey

[英]Java NIO selector.select() always returns only one SelectionKey for OP_ACCEPT SelectionKey

I have written a java NIO server using selector to accept connections from clients. 我编写了一个使用选择器来接受来自客户端的连接的Java NIO服务器。

I thought a selector.select() will block and return multiple keys. 我以为selector.select()将阻止并返回多个键。 I just registered the selector for OP_ACCEPT and it always returns 1 key at a time 我刚刚注册了OP_ACCEPT的选择器,它总是一次返回1个键

Am I doing something wrong? 难道我做错了什么?

package com.bay.srikanth.client;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
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;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

public class FloodServer {

    private final static Logger LOGGER = Logger.getLogger(FloodServer.class.getName());

    private static int PORT = 5555;
    private static ConcurrentHashMap<Integer, SocketChannel> chm
                        = new ConcurrentHashMap<Integer, SocketChannel>();
    private static int msg = 0;
    public static void main(String args[]) throws Exception {
        // Create a new selector
        Selector selector = Selector.open();
        // Open a listener on each port, and register each one
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ServerSocket ss = ssc.socket();            
        InetSocketAddress address = new InetSocketAddress(PORT);
        ss.bind(address);
        //registers ACCEPT
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("Going to listen on " + PORT);

        while (true) {
            LOGGER.log(Level.INFO, "Total active connections : " + chm.size());
            selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            LOGGER.log(Level.INFO, "Selected Keys on : " + selectedKeys + " with keys count : " + selectedKeys.size());
            Iterator<SelectionKey> it = selectedKeys.iterator();            

            while (it.hasNext()) {
                SelectionKey key = (SelectionKey) it.next();
                if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
                    // Accept the new connection
                    ServerSocketChannel sscNew = (ServerSocketChannel) key.channel();
                    SocketChannel sc = sscNew.accept();
                    sc.configureBlocking(false);
                    // Add the new connection to the selector                    
                    //sc.register(selector, SelectionKey.OP_READ);
                    // Add the socket channel to the list
                    chm.put(sc.hashCode(), sc);
                    it.remove();
                }
            }
        }        
    }        
}

Flood Test client tool 洪水测试客户端工具

package com.bay.srikanth.client;

import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.util.List;
import java.util.Vector;

public class FloodTest implements Runnable {

private static List<SocketChannel> channelSet = new Vector<SocketChannel>();

@Override
public void run() {
    try {
        for(int i=0; i<50; i++) {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(true);
            //socketChannel.connect(new InetSocketAddress("10.9.242.70", 5555));
            socketChannel.connect(new InetSocketAddress("localhost", 5555));
            channelSet.add(socketChannel);
        } 
    } catch(Exception ex) {
        System.out.println(ex);
    }
    System.out.println(channelSet.size());
    try {
        Thread.sleep(30000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public static void main(String args[]) throws InterruptedException {
    for(int i=0; i<100; i++) {
        new Thread(new FloodTest()).start();
    }
}

} }

Response log on server: (Partial) 服务器上的响应日志:(部分)

Apr 17, 2014 11:35:49 AM com.bay.srikanth.client.FloodServer main
INFO: Selected Keys on : [sun.nio.ch.SelectionKeyImpl@5e176f] with keys count : 1
Apr 17, 2014 11:35:49 AM com.bay.srikanth.client.FloodServer main
INFO: Total active connections : 2328
Apr 17, 2014 11:35:49 AM com.bay.srikanth.client.FloodServer main
INFO: Selected Keys on : [sun.nio.ch.SelectionKeyImpl@5e176f] with keys count : 1
Apr 17, 2014 11:35:49 AM com.bay.srikanth.client.FloodServer main
INFO: Total active connections : 2329
Apr 17, 2014 11:35:49 AM com.bay.srikanth.client.FloodServer main
INFO: Selected Keys on : [sun.nio.ch.SelectionKeyImpl@5e176f] with keys count : 1
Apr 17, 2014 11:35:49 AM com.bay.srikanth.client.FloodServer main
INFO: Total active connections : 2330
Apr 17, 2014 11:35:49 AM com.bay.srikanth.client.FloodServer main
INFO: Selected Keys on : [sun.nio.ch.SelectionKeyImpl@5e176f] with keys count : 1

Always, Selected Keys on : [sun.nio.ch.SelectionKeyImpl@5e176f] with keys count : 1, the keycount is always 1. I tried increasing threads, still always its 1. 总是在[sun.nio.ch.SelectionKeyImpl@5e176f]上选择键,其键数为1,键数始终为1。我尝试增加线程数,仍然始终为1。

Can someone respond whats wrong here? 有人可以在这里回答错吗?

Thanks, Srikanth 谢谢,Srikanth

Server socket will accept only one at a time . 服务器套接字一次只能接受一个。

When you have multiple sockets on select ie after accepting a client if you register that socket for OP_READ event then you might get two keys when accept and read event happens on the two socket. 如果在选择时有多个套接字,即在接受客户端后如果为OP_READ事件注册了该套接字,则当两个套接字上发生accept和read事件时,您可能会得到两个键。

You will get two or more keys selected only when event happens before executing the statement selector.select(); 仅在执行语句选择器之前发生事件时,您才会选择两个或多个键。

when you are blocking in the select , it will come out after a single event it wont block for multiple events to occur. 当您阻止select时,它将在单个事件后出现,不会阻止多个事件发生。 select() blocks until at least one channel is ready for the events you registered for. select()将阻塞,直到至少一个通道为您注册的事件准备就绪为止。

In your case you have registered only one server socket . 在您的情况下,您仅注册了一个服务器套接字。 so you will get only one key . 所以你只会得到一个钥匙。 I think this answered your question . 我认为这回答了您的问题。

http://tutorials.jenkov.com/java-nio/selectors.html http://tutorials.jenkov.com/java-nio/selectors.html

//sc.register(selector, SelectionKey.OP_READ);

This is the line you need. 这是您需要的线。 It is commented out. 已被注释掉。 Why? 为什么?

NB you also need some code to handle OP_READ when you get it, and you need to make it,remove() unconditional and fail-safe. 注意,在获取OP_READ时,您还需要一些代码来处理它,还需要使其成为无条件且具有故障保护功能的remove()。 Best way to do that is to move it straight after you call it.next(). 最好的方法是在调用it.next()之后将其直接移动。

I think the main key is that your client is just a thread. 我认为主要的关键是您的客户只是一个线程。 althought you have folllow code: 尽管您有以下代码:

for(int i=0; i<50; i++) {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(true);
        //socketChannel.connect(new InetSocketAddress("10.9.242.70", 5555));
        socketChannel.connect(new InetSocketAddress("localhost", 5555));
        channelSet.add(socketChannel);
    }

the 50's request send to server one by one, so your server will accept one by one. 50的请求将一一发送到服务器,因此您的服务器将一一接受。

In summary:Server socket will accept only one at a time 总结:服务器套接字一次只能接受一个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 读取 SelectionKey.isReadable 后,Selector.select() 不会阻塞 - Selector.select() is not blocking after a SelectionKey.isReadable is read SelectionKey.OP_ACCEPT | SelectionKey.OP_WRITE导致IllegalArgumentException - SelectionKey.OP_ACCEPT | SelectionKey.OP_WRITE causes IllegalArgumentException 写入通道后,Java Selector返回带有OP_READ的SelectionKey,而无需在无限循环中的数据 - Java Selector returns SelectionKey with OP_READ without data in infinity loop after writing to channel Java NIO:OP_ACCEPT和OP_READ之间的关系? - Java NIO: Relationship between OP_ACCEPT and OP_READ? 当SelectionKey在java nio中变为可写时 - when a SelectionKey turns writable in java nio Java nio SelectionKey.register和interestops - Java nio SelectionKey.register and interestops 在选择器线程之外的其他线程中设置SelectionKey的interestOps是否安全? (Java Nio) - Is it safe to set interestOps of SelectionKey in other thread than selector thread? (Java Nio) Java 中的 SelectionKey、SelectableChannel 和 Selector 的 C# 类? - C# classes for SelectionKey, SelectableChannel and Selector in Java? java nio 中的 selectionKey.attachment() 是否有任何错误? - is there any bug about selectionKey.attachment() in java nio? 取消后,Java NIO SelectionKey.attachment()发布 - Java NIO SelectionKey.attachment() release upon cancel
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM