bou*_*ert 5 java sockets windows performance
如果我在下面执行JUnit测试而不使用"inputStream.close()"行(见下文),则可以处理超过60000个请求(然后我终止了该过程).有了这一行,我没有管理超过15000个请求,因为:
java.net.SocketException: No buffer space available (maximum connections reached?): connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:529)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.<init>(Socket.java:375)
at java.net.Socket.<init>(Socket.java:189)
at SocketTest.callServer(SocketTest.java:60)
at SocketTest.testResourceConsumption(SocketTest.java:52)
Run Code Online (Sandbox Code Playgroud)
我在Windows上运行它,在开始测试之前我等待netstat列表恢复正常.
问题:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import junit.framework.TestCase;
public class SocketTest extends TestCase {
private static final int PORT = 12345;
private ServerSocket serverSocket;
public void setUp() throws Exception {
serverSocket = new ServerSocket(PORT);
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
final Socket socket = serverSocket.accept();
new Thread(new Runnable() {
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
for(int i = 0; i < 100; i++) {
outputStream.write(i);
}
outputStream.close();
// in fact the previous line calls this already:
// socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}).start();
}
public void testResourceConsumption() throws Exception {
for (int i=0; i<1000000; i++) {
callServer();
if (i % 1000 == 0) {
System.out.println(i);
}
}
}
private void callServer() throws Exception {
Socket clientSocket = new Socket("localhost", PORT);
InputStream inputStream = clientSocket.getInputStream();
for (int i = 0; i < 100; i++) {
assertEquals(i, inputStream.read());
}
///////////////// THIS LINE IS INTERESTING
inputStream.close();
// in fact the previous line calls this already:
// clientSocket.close();
}
public void tearDown() throws Exception {
serverSocket.close();
}
}
Run Code Online (Sandbox Code Playgroud)
当您明确调用时inputStream.close(),更改TCP优雅连接释放的顺序.在这种情况下,连接的客户端在从服务器接收FIN数据包之前关闭,从而使套接字处于TIME_WAIT状态.在某些时候,传出连接的所有本地端口都会被这些TIME_WAIT套接字占用,并且不能再建立传出连接.
当您不打电话时inputStream.close(),服务器端通过outputStream.close()呼叫关闭连接.客户端套接字有足够的时间从服务器接收FIN,然后在垃圾收集时,它们被终结器方法优雅地关闭.
在测试中有两种方法可以修复该过程:
inputStream直到收到-1,这意味着另一方已启动连接关闭(即收到FIN).只需插入assertEquals(-1, inputStream.read());之前inputStream.close();clientSocket.setSoLinger(true, 0);inputStream.close()将强制客户端发送RST并中止连接.| 归档时间: |
|
| 查看次数: |
270 次 |
| 最近记录: |