Java 慢 socket.connect()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4798329/
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
Java slow socket.connect()
提问by coder
Below is the source code of a client and a server. The client just connects (concurrently) to the server and immediatly closes the connection. When all threads are done, it waits 2 minutes and connects again. I am confused about the fact that sometimes a simple connect needs around 3 seconds! Most of the time a connect needs just around 0-32ms.
下面是客户端和服务器的源代码。客户端只是(同时)连接到服务器并立即关闭连接。当所有线程都完成后,它会等待 2 分钟并再次连接。我对有时一个简单的连接需要大约 3 秒的事实感到困惑!大多数情况下,连接只需要大约 0-32 毫秒。
Here a typical output from the client:
这是客户端的典型输出:
...
Connect 23 [ms]: 16
Connect 22 [ms]: 32
Connect 21 [ms]: 32
Connect 15 [ms]: 32
Connect 14 [ms]: 16
Connect 13 [ms]: 16
Connect 11 [ms]: 32
Connect 25 [ms]: 3016
This only seems to happen if client and server are on different hosts. Windows and linux comparable behaviour Java 1.6.23
这似乎只有在客户端和服务器位于不同主机上时才会发生。Windows 和 linux 的可比行为 Java 1.6.23
to start the server 2 parameters are needed: [port] [thread pool size]
启动服务器需要2个参数:[端口] [线程池大小]
to start the client 3 parameters are needed: [host] [port] [thread pool size]
启动客户端需要3个参数:[host] [port] [thread pool size]
for the example i used 150 thread pool size for server and 25 thread pool size for the client.
例如,我为服务器使用了 150 个线程池大小,为客户端使用了 25 个线程池大小。
Can anybody explain this behaviour?
有人可以解释这种行为吗?
----- server -----
- - - 服务器 - - -
package de.test.server;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerApp {
public static void main(String[] args) throws IOException {
System.out.println("server running...");
final int port = Integer.parseInt(args[0]);
final int threads = Integer.parseInt(args[1]);
final ExecutorService executorService = Executors
.newFixedThreadPool(threads);
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
final Socket clientSocket = serverSocket.accept();
executorService.execute(new Runnable() {
@Override
public void run() {
try {
InputStream is = clientSocket.getInputStream();
int read = is.read();
if (read != -1) {
System.out.println("should not happen");
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
close(clientSocket);
System.out.println("connection closed");
}
}
private void close(final Socket connection) {
try {
connection.close();
} catch (IOException e1) {
throw new RuntimeException(e1);
}
};
});
}
}
}
----- client -----
- - - 客户 - - -
package de.test.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
public class ConnectApp {
public static void main(String[] args) throws InterruptedException {
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int THREAD_COUNT = Integer.parseInt(args[2]);
final ExecutorService executorService = Executors
.newFixedThreadPool(THREAD_COUNT);
final AtomicLong threadCounter = new AtomicLong(0);
while (true) {
final CountDownLatch doneSignal = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
Socket socket = null;
try {
long start = System.currentTimeMillis();
socket = new Socket();
socket.setTcpNoDelay(true);
socket.connect(new InetSocketAddress(host, port));
System.out.println(socket.getTcpNoDelay());
long stop = System.currentTimeMillis();
System.out.println("Connect "
+ threadCounter.incrementAndGet() + " [ms]: "
+ (stop - start));
} catch (UnknownHostException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
close(socket);
doneSignal.countDown();
}
}
private void close(Socket socket) {
try {
if (socket != null)
socket.close();
} catch (IOException e1) {
throw new RuntimeException(e1);
}
}
});
}
doneSignal.await();
System.out.println("Waiting 2 minutes...");
Thread.sleep(1000 * 60 * 2);
}
}
}
采纳答案by Peter Lawrey
All your sockets are trying to connect at once. Since they are all trying to connect to the same single threaded server, one will be accept, 50 (by default) will be in the backlog and the reset may not connect or have to wait a particularly long time.
您所有的套接字都在尝试立即连接。由于它们都在尝试连接到同一个单线程服务器,一个将被接受,50 个(默认情况下)将在 backlog 中,并且重置可能无法连接或必须等待特别长的时间。
I suggest trying a 40 ms spacing between attempting to connect to see if this is the problem.
我建议在尝试连接之间尝试 40 毫秒的间隔,看看这是否是问题所在。
BTW: you only call threadCounter.incrementAndGet()
so why is it going up and down? You could just use
BTW:你只跟注threadCounter.incrementAndGet()
,为什么会涨跌?你可以用
for (int i = 0; i < THREAD_COUNT; i++) {
final int threadCount = i;