Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 客户端SocketInputStream.close()是否会导致更多的资源消耗?_Java_Windows_Performance_Sockets - Fatal编程技术网

Java 客户端SocketInputStream.close()是否会导致更多的资源消耗?

Java 客户端SocketInputStream.close()是否会导致更多的资源消耗?,java,windows,performance,sockets,Java,Windows,Performance,Sockets,如果我在没有“inputStream.close()”行的情况下执行下面的JUnit测试(请参见下文),那么可以处理60000多个请求(当时我终止了该进程)。在这一行中,我没有提出超过15000个请求,因为: java.net.SocketException: No buffer space available (maximum connections reached?): connect at java.net.PlainSocketImpl.socketConnect(Native

如果我在没有“inputStream.close()”行的情况下执行下面的JUnit测试(请参见下文),那么可以处理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)
java.net.SocketException:没有可用的缓冲区空间(已达到最大连接数?):连接
位于java.net.PlainSocketImpl.socketConnect(本机方法)
位于java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
位于java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
在java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
位于java.net.socksocketimpl.connect(socksocketimpl.java:366)
位于java.net.Socket.connect(Socket.java:529)
位于java.net.Socket.connect(Socket.java:478)
位于java.net.Socket(Socket.java:375)
位于java.net.Socket(Socket.java:189)
在SocketTest.callServer上(SocketTest.java:60)
测试资源消耗(SocketTest.java:52)
我在Windows上运行它,在开始测试之前,我等待netstat列表恢复正常

问题:

  • 在这种情况下,为什么在客户端调用socketInputStream.close()会造成伤害
  • 或者代码有什么问题

import java.io.IOException;
导入java.io.InputStream;
导入java.io.OutputStream;
导入java.net.ServerSocket;
导入java.net.Socket;
导入junit.framework.TestCase;
公共类SocketTest扩展了TestCase{
专用静态最终int端口=12345;
私有服务器套接字服务器套接字;
public void setUp()引发异常{
serverSocket=新的serverSocket(端口);
新线程(newrunnable()){
@凌驾
公开募捐{
while(true){
试一试{
最终套接字=serverSocket.accept();
新线程(newrunnable()){
@凌驾
公开募捐{
试一试{
OutputStream OutputStream=socket.getOutputStream();
对于(int i=0;i<100;i++){
outputStream.write(i);
}
outputStream.close();
//事实上,前一行已经调用了:
//socket.close();
}捕获(IOE异常){
抛出新的运行时异常(e);
}
}
}).start();
}捕获(例外e){
抛出新的运行时异常(e);
}
}
}
}).start();
}
public void testResourceConsumption()引发异常{

对于(int i=0;i当显式调用
inputStream.close()时)
更改TCP优雅连接释放的顺序。在这种情况下,连接的客户端在从服务器接收FIN数据包之前关闭,从而使套接字处于TIME\u WAIT状态。在某个时候,用于传出连接的所有本地端口都被这些TIME\u WAIT套接字占用,不再有传出连接c必须作出决定

当您不调用
inputStream.close()
时,服务器端会通过调用
outputStream.close()
关闭连接。客户端套接字有足够的时间从服务器接收FIN,然后在垃圾收集时,它们会通过终结器方法正常关闭

有两个选项可以修复测试中的过程:

  • 更好的方法是继续从
    inputStream
    读取,直到您收到-1,这意味着另一方已经启动了连接关闭(即接收到FIN)。只需在
    inputStream.close()之前插入
    assertEquals(-1,inputStream.read());
  • 第二个选项是通过设置
    clientSocket.setSoLinger(true,0);

    在这种情况下,
    inputStream.close()
    将强制客户端发送RST并中止连接

  • 确定你没有背对背吗?你能提供有关Windows版本、平台32或64位以及java版本的更多信息吗?仅供参考,我在Ubuntu 15.04上运行了你的测试。它完成了所有百万次迭代,没有错误。在执行期间的任何给定时间,状态时间中大约有28000个套接字等待。(这是由于执行和打开新套接字的速度)作为参考,只有第二个选项(强制关闭)在OSX上的Java8上对我有效。
    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();
        }
    
    }