Socket编程与NIO
问题描述:
我与NIO今天早些时候乱搞和numClients
了(我的电脑〜2500
)越大,我开始收到以下异常:Socket编程与NIO
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);
}
}
这种情况下,我的电脑无法跟上请求,或者是在这里发生的更险恶的事情?谷歌搜索没有任何用处。
可能相关的信息:
Java版本 “1.7.0_02”
的Java(TM)SE运行时环境(建立1.7.0_02-B13)
的HotSpot的Java(TM)客户端虚拟机(建设22.0 - B10,混合模式,共享)
32位Windows 7家庭高级版SP 1
AMD炫龙M500双核2.20 GHz的
2.00 GB内存
瑞昱RTL8191SE无线网络的802.11n PCI-E网卡
答
您在连续打开数千个客户端连接时没有中介休眠,因此您可能会溢出ServerSocketChannel的监听积压队列,此时Windows开始拒绝连接。无论您使用这种技术进行测试,它都不是一个有效的测试,因为您(a)挨饿运行的服务器线程并且(b)可能将耗尽出站端口空间,此时您将如果你可以超越你目前的问题,就可以在connect()上获取BindExceptions。
此外,您并未关闭您的连接和接受的频道,只是永远积累它们。所以当你到达numClients = 2500
时,你有5000个插座打开,你知道吗?