NIO server cannot listen to client

Hi I am trying to implement a simple Java NIO server; which registers socketChannel with a selector. So I want to listen to the client and send a response. After the socketChannel is registered with the selector, even if the client (non-NIO) sends some data, the server cannot read; howerver the generated key is still being repeated.

Detailed View: Server Side:

**First thread**:

      

public void run () {while (true) {

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.configureBlocking(true);
    serverSocketChannel.socket().bind(inetAdressOfServer);
    SocketChannel clientChannel = serverSocketChannel.accept();
    new Listener("").addSocketChannel(clientChannel);

}}

**Second Thread**:

    static Selector selector = Selector.open();
    public boolean addSocketChannel(SocketChannel clientChannel) {

        SelectionKey key = clientSocketChannel.register(selector, selector.OP_READ|SelectionKey.OP_WRITE);              
        key.attach(new ChannelCallback(clientSocketChannel));
        return key.isValid();
    }

    public void run() {

        Set keysSet = selector.keys();
        Iterator i = keysSet.iterator();        
        while (i.hasNext()) {
            SelectionKey key = (SelectionKey) i.next();
        }

        if (key.isReadable()) {
            //read and do something
        }
    }



Client Side:

Socket socket = new Socket(serverIP, serverPort);    
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());    
dos.writeBytes(str + "\n");

      

NB: when executed in the same thread, the same program is running, but when implemented according to the above method, it prevents the client from listening. Please help me to solve this problem.

+1


a source to share


2 answers


It is very difficult to understand what you did there, but it looks like what you marked as "second thread" is being used by both threads (some confusion about implementation Runnable

/ extend Thread

and real threads?). In particular, I am assuming the construct new Listener

and start the thread. Then you call addSocketChannel

on the first thread. Therefore, there is a race condition.



It's also a bad idea to make selector

static.

+1


a source


Reading reading reading from another thread, here are the obvious problems with your code.

public void run() {
    Set keysSet = selector.keys();

      

Here you are taking a set of keys from an iterator, but there is no code ever doing select () or selectNow () on a selector, so that set will always be empty.

    Iterator i = keysSet.iterator();        
    while (i.hasNext()) {
        SelectionKey key = (SelectionKey) i.next();
    }
    if (key.isReadable()) {
        //read and do something
    }
}

      

It doesn't even compile, the "read" check on the key must be done inside the while block.



SelectionKey key = clientSocketChannel.register(selector,
                                                SelectionKey.OP_READ | 
                                                SelectionKey.OP_WRITE);              

      

Two problems: the channel must be set in non-blocking mode before then, and SelectionKey.OP_WRITE must not be set unless you want the key to be returned every time you run select.

You only need to set SelectionKey.OP_WRITE if you actually plan on writing.

Finally, using two streams is very unconventional here. The recommended way to do this is to register the ServerSocketChannel for the selector with OP_ACCEPT and run accept on the ServerSocket on the same thread as the read / write.

+1


a source







All Articles