Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NIO client giving exception : java.net.ConnectException: Connection refused: no further information

Tags:

java

nio

I modified the sample code available here for Client and Server My client :

public class Client {

public static void main(String[] args) {

    int n=10000;
    SocketTest [] st= new SocketTest[n];
    for(int i=0;i<n;i++)
        st[i]= new SocketTest("hi");

    for(int i=0;i<n;i++)
        new Thread(st[i]).start();
   }
}
class SocketTest implements Runnable {

    private String message = "";
    private Selector selector;
    private int i;


    public SocketTest(String message){
        this.message = message;
    }

    @Override
    public void run() {
        SocketChannel channel;
        try {
            selector = Selector.open();
            channel = SocketChannel.open();
            channel.configureBlocking(false);

            channel.register(selector, SelectionKey.OP_CONNECT);
            channel.connect(new InetSocketAddress("127.0.0.1", 8511));


            while (!Thread.currentThread().isInterrupted()){

                selector.select();

                Iterator<SelectionKey> keys = selector.selectedKeys().iterator();

                while (keys.hasNext()){
                    SelectionKey key = keys.next();
                    keys.remove();

                    if (!key.isValid()) continue;

                    if (key.isConnectable()){                           
                            connect(key);
                        System.out.println("I am connected to the server");
                    }   
                    if (key.isWritable()){
                        write(key);
                    }
                    if (key.isReadable()){
                        read(key);
                    }
                }   
            }
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } finally {
            close();
        }
    }

    private void close(){
        try {
            selector.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void read (SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer readBuffer = ByteBuffer.allocate(1000);
        readBuffer.clear();
        int length;
        try{
        length = channel.read(readBuffer);

        } catch (IOException e){
            System.out.println("Reading problem, closing connection");
            key.cancel();
            channel.close();
            return;
        }
        if (length == -1){
            System.out.println("Nothing was read from server");
            channel.close();
            key.cancel();
            return;
        }
        readBuffer.flip();
        byte[] buff = new byte[1024];
        readBuffer.get(buff, 0, length);
        //length=buff.length;

        String fromserver = new String(buff,0,length,"UTF-8");
        length = fromserver.length();
        System.out.println("Server said: "+fromserver);

        key.interestOps(SelectionKey.OP_WRITE);
    }

    private void write(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        i++;
        message = "location now "+i;
        try{
            Thread.sleep(5000);

        }
        catch(InterruptedException ie)
        {
            System.out.println(""+ie);
        }
        channel.write(ByteBuffer.wrap(message.getBytes()));

        // lets get ready to read.
        key.interestOps(SelectionKey.OP_READ);
    }

    private void connect(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        try
        {
            if(!channel.finishConnect())
                System.out.println("* Here *");
        }
        catch(ConnectException e)
        {
            System.out.println("BP 1");
            e.printStackTrace();

            //channel.close();
            //key.cancel();
            //return;
        }
        /*if (channel.isConnectionPending()){
            while(!channel.ffinishConnect()){
                System.out.println("not connected");
            }
        }*/

        channel.configureBlocking(false);
        channel.register(selector, SelectionKey.OP_WRITE);
    }
}

I create multiple clients on the same machine by creating multiple threads. No of threads are determined by value of n. When I run small no of clients I encounter no problem but as soon as I run with n as 500 i.e. 500 client threads , some threads run correctly but in some I encounter this : java.net.ConnectException: Connection refused: no further information at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source) at SocketTest.connect(Client.java:143) at SocketTest.run(Client.java:61)

Line 143 is : if(!channel.finishConnect()) So when I read documentation of this method it says it throws :

NoConnectionPendingException - If this channel is not connected and a connection operation has not been initiated.

ClosedChannelException - If this channel is closed.

AsynchronousCloseException - If another thread closes this channel while the connect operation is in progress.

ClosedByInterruptException - If another thread interrupts the current thread while the connect operation is in progress, thereby closing the channel and setting the current thread's interrupt status.

IOException - If some other I/O error occurs.

But the Exception is ConnectException. I tried catching it but it doesn't go into catch block.

Any help will be appreciated. Thanks. EDIT : I am working on windows. I tried changing value of n see how many client were created and how many caused exceptions and these are the results(I know waiting for more time after each test will allow for more open sockets as after each test scokets will be released after TIME_WAIT ) :

n clients connected(by keeping a count at server) 1000 522 2000 568 3000 626 4000 600 (maybe I gave less time before successive runs) 5000 1345 6000 1389 I am problemed by how can only these many clients are getting connected. Can anyone please suggest better references to read for Client Server NIO.

EDIT 2

As EJP mentioned in his comment the window Backlog Queue was full. I modified Client code to generate 100 threads and then sleep for 5 seconds and this way there was not much load on Queue and most of the connection were successful(however still when making 10,000 connections some still failed).

like image 244
cruxion effux Avatar asked May 27 '15 04:05

cruxion effux


People also ask

How do I fix Java net ConnectException Connection refused No further information?

ConnectException: Connection refused: 1) First try to ping the destination host, if the host is ping-able it means the client and server machine are in the network. 2) Try connecting to server host and port using telnet. If you are able to connect means something is wrong with your client code.

How do I fix Java net ConnectException Connection refused connect?

How do you handle Java net ConnectException connection refused? Ans: To resolve the Java net error, first try to ping the destination host, if you are able to ping the host means the client and server machine are in the proper network. Your next step should be connecting to the server host and port using telnet.

What is Java net ConnectException connection refused?

net. ConnectException: Connection refused: connect is the most frequent kind of occurring networking exception in Java whenever the software is in client-server architecture and trying to make a TCP connection from the client to the server.

How do you handle ConnectException?

ConnectException exception is one of the most common Java exceptions related to networking. We may encounter it when we're establishing a TCP connection from a client application to a server. As it's a checked exception, we should handle it properly in our code in a try-catch block.


2 Answers

ConnectException: connection refused means nothing was listening at the IP:port you tried to connect to, or on some platforms that the server's listen-backlog queue filled up. If it is thrown and you catch it correctly, you will certainly catch it. You would have to expand on what actually happens and what your actual catch code looks like for further assistance.

However you have many other problems:

private void connect(SelectionKey key) throws IOException {
    SocketChannel channel = (SocketChannel) key.channel();
    try
    {
        if(!channel.finishConnect())
            System.out.println("* Here *");

At this point, if finishConnect() returned false, you should return. You should not fall through and re-register the channel for OP_WRITE. The connection is still pending. Printing "* Here *" is also pretty futile. Try printing something meaningful.

    }
    catch(ConnectException e)
    {
        System.out.println("BP 1");
        e.printStackTrace();

        //channel.close();

You should certainly close the channel at this point. It is of no further use to man or beast.

        //key.cancel();

Closing the channel cancels the key. Remove wherever encountered.

        //return;

As above, you should certainly return at this point.

    }
    /*if (channel.isConnectionPending()){
        while(!channel.ffinishConnect()){
            System.out.println("not connected");
        }
    }*/

Get rid of this crud. It is never appropriate to spin-loop in non-blocking mode. Don't even leave it lying around as comments: some idiot may come along later and play with putting it back.

    channel.configureBlocking(false);

The channel is already in non-blocking mode. Otherwise you wouldn't be here. Remove.

    channel.register(selector, SelectionKey.OP_WRITE);

Another way to do that is key.interestOps(SelectionKey.OP_WRITE);

Sleeping in networking code is literally a waste of time. It doesn't solve anything.

You are assuming that write() succeeded completely, and you're ignoring the count it returns.

You're using a fairly poor quality reference:

  • Same remarks about write() apply as above.
  • flip() is not 'like a reset'.
  • Cancelling a key closes the channel.
  • You don't have to clear a brand-new ByteBuffer, but in any case allocating a ByteBuffer per read is poor practice.
  • ServerSocketChannel.accept() can return null.
  • The code that displays a String after reading is incorrect.
  • There is no need to use a Map when keys have attachments.
  • There's no need to keep testing Thread.interrupted() when NIO is interruptible anyway.
  • There's no need to close everything just becaues of one IOException on one channel.

Try to find something better.

like image 150
user207421 Avatar answered Sep 28 '22 19:09

user207421


I believe the ConnectException you are getting with 500 threads is not coming from SocketTest.connect(). It could be coming from any of the other IO methods.

For a quick fix (and to convince yourself), you can explicitly catch ConnectException in your main try-catch block like this:

try {
    // connect, write, and read ...
} catch (ConnectException ce) {  // <-- catch the more specific Exception first
    System.out.println("You caught a ConnectException.");
} catch (IOException e1) {       // <-- you originally only caught this
    // TODO Auto-generated catch block
    e1.printStackTrace();
} finally {

As to why this is happening, I can tell you that I am currently ramping up to hundreds of threads for testing a SOAP service. I also get dropped connections all over the place, so maybe this is to be expected with such a large number of concurrent threads.

like image 40
Tim Biegeleisen Avatar answered Sep 28 '22 18:09

Tim Biegeleisen