Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

infinited loop with java selector

Tags:

java

selector

nio

I am a new comer in Java, now I got puzzled with java nio selector, below are the code from the book of java network program 3rd,

package org.eclipse.java.socket.samples;

import java.io.IOException;
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;

public class ChargenServer {
    public static int DEFAULT_PORT = 4321;
    public static void main(String[] args) {
        int port;
        try {
            port = Integer.parseInt(args[0]);
        }
        catch (Exception ex) {
            port = DEFAULT_PORT;
        }
        System.out.println("Listening for connections on port " + port);
        byte[] rotation = new byte[95 * 2];
        for (byte i = ' '; i <= '~'; i++) {
            rotation[i - ' '] = i;
            rotation[i + 95 - ' '] = i;
        }
        ServerSocketChannel serverChannel;
        Selector selector;
        try {
            serverChannel = ServerSocketChannel.open();
            ServerSocket ss = serverChannel.socket();
            InetSocketAddress address = new InetSocketAddress(port);
            ss.bind(address);
            serverChannel.configureBlocking(false);
            selector = Selector.open();
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        }
        catch (IOException ex) {
            ex.printStackTrace();
            return;
        }
        while (true) {
            try {
                selector.select();
            }
            catch (IOException ex) {
                ex.printStackTrace();
                break;
            }            
            Set<SelectionKey> readyKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = readyKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = (SelectionKey) iterator.next();
                iterator.remove();
                try {
                    if (key.isAcceptable()) {
                        ServerSocketChannel server = (ServerSocketChannel) key
                                .channel();
                        SocketChannel client = server.accept();
                        System.out
                                .println("Accepted connection from " + client);
                        client.configureBlocking(false);
                        SelectionKey key2 = client.register(selector,
                                SelectionKey.
                                OP_WRITE);
                        ByteBuffer buffer = ByteBuffer.allocate(74);
                        buffer.put(rotation, 0, 72);
                        buffer.put((byte) '\r');
                        buffer.put((byte) '\n');
                        buffer.flip();
                        key2.attach(buffer);
                    }
                    else if (key.isWritable()) {
                        SocketChannel client = (SocketChannel) key.channel();
                        ByteBuffer buffer = (ByteBuffer) key.attachment();
                        if (!buffer.hasRemaining()) {
                            // Refill the buffer with the next line
                            buffer.rewind();
                            // Get the old first character
                            int first = buffer.get();
                            // Get ready to change the data in the buffer
                            buffer.rewind();
                            // Find the new first characters position in
                            // rotation
                            int position = first - ' ' + 1;
                            // copy the data from rotation into the buffer
                            buffer.put(rotation, position, 72);
                            // Store a line break at the end of the buffer
                            buffer.put((byte) '\r');
                            buffer.put((byte) '\n');
                            // Prepare the buffer for writing
                            buffer.flip();
                            buffer.compact();
                        }
                        client.write(buffer);
                    }
                }
                catch (IOException ex) {
                    key.cancel();
                    try {
                        key.channel().close();
                    }
                    catch (IOException cex) {
                    }
                }
            }
        }
    }
}

The server is quite simple, get a connection, then echo a serial letters to the clients, but when i run it on my Ubuntu10.10 with

Java version "1.6.0_20"

OpenJDK Runtime Environment (IcedTea6 1.9.4) (6b20-1.9.4-0ubuntu1)

OpenJDK Server VM (build 19.0-b09, mixed mode)

I got a infinite loop, I really do not know why, help me please!

Thanks everybody, but i still be confused with selector, now let's make things more easy to show my confused, see the code:

package org.eclipse.java.socket.selector;

import java.io.IOException;
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 SocketSelector {
    public static void main(String[] args) throws IOException {
        // Create selector
        Selector selector = null;
        selector = Selector.open();
        ////////////////////////////////////////////////////////////////////////
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(
                "localhost", 4321));
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_CONNECT);
        /*
         * Let's begin select
         */
        while (true) {
            selector.select();
            System.out.println("Hello, selector!");
            Set readyKeys = selector.selectedKeys();
            Iterator it = readyKeys.iterator();  
            while (it.hasNext()) {
                SelectionKey key = (SelectionKey )it.next();
                if (key.isReadable()) {
                    System.out.println("It's readable!");
                }
                it.remove();
            }
        }
    }
}

in my understand, "selector.select()" wait a input event from remote server, then it.remove() remove this event, so the selector begin to wait for new event from remote server, so the client can get data from server with selector in a continuous way, but the result is looped again and again, the selector make no sense to the server's data, why? Anything wrong with my code?

like image 477
liunx Avatar asked May 09 '26 16:05

liunx


1 Answers

Three are multiple issues w/ the code, incl. not closing the selectors.

You need to register for OP_WRITE only if the write operation fails to write the entire Buffer, and unregister otherwise. Look at interestedOps().

Generally, you need OP_READ in order to read from that channel. Finally ALWAYS check http://bugs.sun.com before stackoverflow (it's one of my tracked bugs). Advise: don't use the same selector to accept/write.

https://bugs.java.com/bugdatabase/view_bug?bug_id=4919127

cheers

like image 163
2 revsbestsss Avatar answered May 12 '26 07:05

2 revsbestsss