NIO 客户端给出异常:java.net.ConnectException:连接被拒绝:没有更多信息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30473163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:10:59  来源:igfitidea点击:

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

javanio

提问by cruxion effux

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

我修改了此处为 Client 和 ServerMy 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)

我通过创建多个线程在同一台机器上创建多个客户端。线程数由 n 值决定。当我运行很少的客户端时,我没有遇到任何问题,但是一旦我使用 n 为 500 即 500 个客户端线程运行,某些线程可以正确运行,但在某些线程中我遇到了这个问题: 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 :

第 143 行是: if(!channel.finishConnect())所以当我阅读此方法的文档时,它说它抛出:

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.

NoConnectionPendingException- 如果此通道未连接且未启动连接操作。

ClosedChannelException- 如果此通道已关闭。

AsynchronousCloseException- 如果在连接操作正在进行时另一个线程关闭此通道。

ClosedByInterruptException- 如果在连接操作正在进行时另一个线程中断当前线程,从而关闭通道并设置当前线程的中断状态。

IOException- 如果发生其他一些 I/O 错误。

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

但异常是 ConnectException。我试图抓住它,但它没有进入 catch 块。

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 ) :

任何帮助将不胜感激。谢谢。 编辑:我在 Windows 上工作。我尝试更改 n 的值,看看创建了多少个客户端以及有多少个导致异常,这些是结果(我知道在每次测试后等待更多时间将允许更多打开的套接字,因为在 TIME_WAIT 之后每个测试 scokets 将被释放):

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.

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 我的问题是如何只有这么多客户端才能连接。任何人都可以建议更好的参考来阅读客户端服务器 NIO。

EDIT 2

编辑 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).

正如 EJP 在他的评论中提到的,窗口积压队列已满。我修改了客户端代码以生成 100 个线程,然后休眠 5 秒,这样队列上的负载并不多,并且大部分连接都成功了(但是在建立 10,000 个连接时仍然有一些连接失败)。

采纳答案by user207421

ConnectException: connection refusedmeans 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.

ConnectException: connection refused意味着没有任何东西在您尝试连接的 IP:port 上侦听,或者在服务器的侦听积压队列已填满的某些平台上。如果它被抛出并且你正确地抓住它,你肯定会抓住它。您将不得不扩展实际发生的事情以及您的实际捕获代码的样子以获得进一步的帮助。

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 notfall through and re-register the channel for OP_WRITE.The connection is still pending. Printing "* Here *"is also pretty futile. Try printing something meaningful.

此时,如果finishConnect()返回false,则应返回。你应该不会落空,并重新注册为通道OP_WRITE.的连接仍悬而未决。打印"* Here *"也很无用。尝试打印一些有意义的东西。

    }
    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);

另一种方法是 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.

您假设write()完全成功,并且您忽略了它返回的计数。

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 ByteBufferper 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 Mapwhen 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 IOExceptionon one channel.
  • 关于write()应用的相同评论与上述相同。
  • flip()不是“像重置”。
  • 取消一个键会关闭通道。
  • 您不必清除一个全新的,ByteBuffer,但无论如何分配ByteBuffer每次读取都是不好的做法。
  • ServerSocketChannel.accept()可以返回 null.
  • 读取后显示字符串的代码不正确。
  • Map当键有附件时不需要使用 a 。
  • Thread.interrupted()无论如何,当 NIO 可中断时,无需继续测试。
  • 没有必要仅仅因为IOException一对一频道而关闭所有内容。

Try to find something better.

尝试找到更好的东西。

回答by Tim Biegeleisen

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

我相信ConnectException你得到的 500 个线程不是来自SocketTest.connect(). 它可能来自任何其他 IO 方法。

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

为了快速修复(并说服自己),您可以像这样显式地捕获ConnectExceptiontry-catch块:

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.

至于为什么会发生这种情况,我可以告诉您,我目前正在增加数百个线程来测试 SOAP 服务。我的连接也到处都是断开的,所以对于如此大量的并发线程,这可能是意料之中的。

回答by akshat thakar

Try doing Telnet using command -

尝试使用命令执行 Telnet -

telnet [host IP] [port] 

Issue may be with firewall blocking port.

问题可能与防火墙阻止端口有关。