Программирование сокетов с NIO - PullRequest
1 голос
/ 23 февраля 2012

Сегодня я возился с NIO и, когда numClients стал больше (~ 2500 для моего компьютера), я начал получать следующее исключение:

java.net.ConnectException: Connection refused: no further information
    at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
    at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:701)
    at SocketInformationExceptionTest.run(SocketInformationExceptionTest.java:49)
    at java.lang.Thread.run(Thread.java:722)

Из этого кода:

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
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.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class SocketInformationExceptionTest implements Runnable {
    private static interface Request {
        public void process(Selector sel);
    }

    private final Selector selector;
    private final BlockingQueue<Request> requests = new LinkedBlockingQueue<>();

    public SocketInformationExceptionTest() throws IOException {
        selector = Selector.open();
    }

    public void addRequest(Request r) {
        requests.add(r);
        selector.wakeup();
    }

    @Override
    public void run() {
        while (true) {
            while (!requests.isEmpty()) {
                Request r = requests.poll();
                r.process(selector);
            }
            try {
                selector.select();

                Iterator<SelectionKey> itr = selector.selectedKeys().iterator();
                while (itr.hasNext()) {
                    SelectionKey key = itr.next();
                    itr.remove();

                    if (key.isValid()) {
                        if (key.isAcceptable()) {
                            ((ServerSocketChannel) key.channel()).accept();
                        } else if (key.isConnectable()) {
                            ((SocketChannel) key.channel()).finishConnect();
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        int numClients = 2500;

        SocketInformationExceptionTest test = new SocketInformationExceptionTest();
        new Thread(test).start();

        final ServerSocketChannel server = ServerSocketChannel.open().bind(
                new InetSocketAddress(1234));
        server.configureBlocking(false);

        test.addRequest(new Request() {
            @Override
            public void process(Selector sel) {
                try {
                    server.register(sel, SelectionKey.OP_ACCEPT);
                } catch (ClosedChannelException e) {
                    e.printStackTrace();
                }
            }
        });

        for (int x = 0; x < numClients; x++) {
            final SocketChannel socket = SocketChannel.open();
            socket.configureBlocking(false);
            socket.connect(new InetSocketAddress(InetAddress.getLocalHost(),
                    1234));

            test.addRequest(new Request() {
                @Override
                public void process(Selector sel) {
                    try {
                        socket.register(sel, SelectionKey.OP_CONNECT);
                    } catch (ClosedChannelException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        System.exit(0);
    }
}

Это тот случай, когда мой компьютер просто не справляется с запросами или здесь происходит что-то более зловещее?Поиск в Google ничего не дал.

Потенциально важная информация:
Java-версия "1.7.0_02"
Java (TM) SE Runtime Environment (сборка 1.7.0_02-b13)
Java HotSpot(TM) Клиентская виртуальная машина (сборка 22.0-b10, смешанный режим, совместное использование)

32-разрядная Windows 7 Home Premium SP 1
Двухъядерный процессор AMD Turion M500 2,20 ГГц
2,00 ГБ Память
Realtek RTL8191SE Беспроводная локальная сеть 802.11n PCI-E NIC

1 Ответ

3 голосов
/ 23 февраля 2012

Вы открываете тысячи клиентских подключений подряд без промежуточных снов, поэтому вы, вероятно, собираетесь переполнить очередь прослушивания невыполненной работы ServerSocketChannel, после чего Windows начинает отказывать в подключениях.Независимо от того, что вы тестируете с помощью этой методики, это недопустимый тест, поскольку вы (а) лишаете серверный поток возможности запуска и (б) возможно собираетесь исчерпать пространство исходящего порта, после чего вы будетеначните получать исключения BindException для connect (), если вы можете обойти текущую проблему.

Кроме того, вы не закрываете свои подключенные и принятые каналы, просто накапливаете их навсегда.Итак, когда вы достигаете numClients = 2500 у вас есть 5000 открытых розеток, вы понимаете это?

...