【问题标题】:Connection refused after connecting 75 clients to server将 75 个客户端连接到服务器后连接被拒绝
【发布时间】:2014-12-25 13:25:04
【问题描述】:

我使用以下代码开发了一个服务器通道套接字:

public class EchoServer {
private static final int BUFFER_SIZE = 1024;

private final static int DEFAULT_PORT = 9090;

private long numMessages = 0;

private long loopTime;

private InetAddress hostAddress = null;

private int port;

private Selector selector;

// The buffer into which we'll read data when it's available
private ByteBuffer readBuffer = ByteBuffer.allocate(BUFFER_SIZE);

int timestamp=0;

public EchoServer() throws IOException {
    this(DEFAULT_PORT);
}

public EchoServer(int port) throws IOException {
    this.port = port;
    hostAddress = InetAddress.getByName("127.0.0.1");
    selector = initSelector();
    loop();
}

private Selector initSelector() throws IOException {
    Selector socketSelector = SelectorProvider.provider().openSelector();

    ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(false);

    InetSocketAddress isa = new InetSocketAddress(hostAddress, port);
    serverChannel.socket().bind(isa);
    serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT);
    return socketSelector;
}

private void loop() {
    for (;true;) {
        try {
            selector.select();
            Iterator<SelectionKey> selectedKeys = selector.selectedKeys()
                    .iterator();
            while (selectedKeys.hasNext()) {
                SelectionKey key = selectedKeys.next();
                selectedKeys.remove();
                if (!key.isValid()) {
                    continue;
                }
                 // Check what event is available and deal with it
                if (key.isAcceptable()) {
                    accept(key);
                } else if (key.isWritable()) {
                    write(key);
                }
            }
            Thread.sleep(3000);
            timestamp+=3;
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }



    }
}

private void accept(SelectionKey key) throws IOException {

    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();

    SocketChannel socketChannel = serverSocketChannel.accept();
    socketChannel.configureBlocking(false);
    socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
    socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
  //  socketChannel.register(selector, SelectionKey.OP_READ);
    socketChannel.register(selector, SelectionKey.OP_WRITE);

    System.out.println("Client is connected");
}

private void write(SelectionKey key) throws IOException {
    SocketChannel socketChannel = (SocketChannel) key.channel();
    ByteBuffer dummyResponse = ByteBuffer.wrap(("ok:" + String.valueOf(timestamp)) .getBytes("UTF-8"));

    socketChannel.write(dummyResponse);
    if (dummyResponse.remaining() > 0) {
        System.err.print("Filled UP");
    }
    System.out.println("Message Sent");
 //   key.interestOps(SelectionKey.OP_READ);
}

}

如您所见,我在localhost 端口9090 上运行它。为了测试重连接的代码,我开发了一个测试应用程序,它每秒运行一个新线程并连接到服务器。这是我的测试应用的代码:

    public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        int i = 0;
        try {
            while (i < 10000) {
                RunnableDemo temp = new RunnableDemo("Thread-"
                        + String.valueOf(i));
                temp.start();
                i++;
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class RunnableDemo implements Runnable {
    private Thread t;
    private String threadName;

    InetAddress host = null;
    int port = 9090;

    RunnableDemo(String name) {
        threadName = name;
        System.err.println("Creating " + threadName);

    }

    public void run() {
        System.err.println("Running " + threadName);
        try {
            SocketChannel socketChannel = SocketChannel.open();

            socketChannel.connect(new InetSocketAddress(host, port));

            while (!socketChannel.finishConnect())
                ;

            System.out.println("Thread " + threadName + " Connected");
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (true) {
                if (socketChannel.read(buffer) > 0) {
                    buffer.flip();
                    byte[] bytes = new byte[buffer.limit()];
                    buffer.get(bytes);  
                    System.out.println(threadName+ ":" + new String(bytes));
                    buffer.clear();
                }
            }

        } catch (Exception e) {
            System.out.println("Thread " + threadName + " interrupted.");
            e.printStackTrace();
        }
        System.out.println("Thread " + threadName + " exiting.");
    }

    public void start() {
        System.out.println("Starting " + threadName);
        try {
            host = InetAddress.getByName("127.0.0.1");
            if (t == null) {
                t = new Thread(this, threadName);
                t.start();
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

}

测试应用程序运行但只有 75 个线程可以连接到服务器,并且 75 号之后的所有线程都显示以下异常:

java.net.ConnectException: Connection refused: connect
at sun.nio.ch.Net.connect0(Native Method)
at sun.nio.ch.Net.connect(Unknown Source)
at sun.nio.ch.Net.connect(Unknown Source)
at sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
at net.behboodi.client.RunnableDemo.run(Main.java:48)
at java.lang.Thread.run(Unknown Source)

对套接字的并发连接数是否有任何限制?或者使用端口 127.0.0.1 和本地主机是否有任何限制?另一个想法是,Java 应用程序或 JVM 可能不能创建超过 75 个线程。

我搜索了所有这些,但没有找到任何答案来说明上述原因是我的主要问题以及如何修复代码以便我可以测试具有超过 10000 个并发线程的应用程序?

【问题讨论】:

  • 它不是 Java,无论是线程数还是套接字连接数。您的程序在 Linux 系统上运行超过 100 个客户端连接。你在窗户上吗?
  • 是的,我在 Windows 上。但是如何扩展 Windows 或 linux 中的线程数。我正在标记 10000 个客户端线程。
  • 这不是导致问题的线程数,因为您可以在其自己的线程中启动第 75 个客户端。对我来说,它看起来更像是一个套接字资源限制。恐怕我无法在 Windows 方面为您提供帮助。
  • 您实际在哪个操作系统版本上运行它?
  • 摆脱睡眠。选择器已经阻塞。沉睡在网络代码中简直是浪费时间。注意(1)您不要在阻塞模式下调用finishConnect(),(2)您没有将线程连接到ServerChannel,您正在将客户端套接字连接到服务器套接字,(3)您的客户端代码不处理结束流,并且 (4) 这不是回显服务器。

标签: java windows multithreading sockets heavy-computation


【解决方案1】:

摆脱睡眠。选择器已经阻塞。沉睡在网络代码中简直是浪费时间。注意(1)您不要在阻塞模式下调用 finishConnect(),(2)您没有将线程连接到 ServerChannel,您正在将客户端套接字连接到服务器套接字,(3)您的客户端代码不处理 end流,并且 (4) 这不是回显服务器。 – EJP

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 2014-01-10
    • 1970-01-01
    相关资源
    最近更新 更多