[英]Connection refused after connecting 75 clients to server
我使用以下代碼開發了服務器通道套接字:
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個並發線程測試該應用程序?
擺脫睡眠。 選擇器已被阻止。 睡在網絡代碼中實際上只是浪費時間。 注意:(1)您不要在阻塞模式下調用finishConnect()
,(2)您沒有將線程連接到ServerChannel,您正在將客戶端套接字連接到服務器套接字,(3)您的客戶端代碼無法處理結束(4)這不是回顯服務器。 – EJP
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.