Java套接字:没有可用的缓冲区空间(达到最大连接数?)

时间:2014-10-16 16:49:28

标签: java multithreading sockets

我有一个大问题。我开发了一个客户端 - 服务器应用程序。客户端线程将序列化对象发送到服务器,服务器发回序列化对象。目前我使用一个服务器和10个客户端线程,大约30秒后,我从每个客户端线程收到错误消息(IOException):

  

没有可用的缓冲区空间(达到最大连接数?):connect

如果我正在查看netstat,那么我发现创建了很多连接,并且它正在增长和增长,并且所有连接都处于TIME_WAIT状态。

我不知道为什么。我每次都在finally块中关闭服务器和客户端中的套接字。这是一些代码:

在socketHandlerThread:

中的服务器中
ServerSocket serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(5000);
while(true) {
       Socket socket = serverSocket.accept();
}

然后将新套接字放在LinkedBlockingQueue上,工作线程接受套接字并执行以下操作:

try {
      outputStream = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
      outputStream.flush();
      inStream = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
      ClientRequest clientRequest = (ClientRequest) inStream.readObject();
...
      outputStream.writeObject(serverResponse);
      outputStream.flush();
} catch....
} finally {
                if (inStream != null) {
                    inStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                if (socket != null) {
                    socket.close();
                }
}

在客户端,我有以下代码:

    try {
        socket = new Socket(host, port);
        outputStream = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        outputStream.flush();
        inputStream = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
        outputStream.writeObject(request);
        outputStream.flush();
        Object serverResponse = inputStream.readObject();
   } catch....
   } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
            if (socket != null) {
                socket.close();
            }
   }

有人可以帮忙吗?我真的不知道自己犯了什么错误。我似乎插座没有关闭,但我不知道为什么。

问题是我将套接字放在服务器端的队列中以便以某种方式复制套接字吗?

编辑:如果我将客户端和服务器分别放在运行Linux AMI的其他Amazon EC2经典实例上,那么它可以运行。这可能是Windows的一个问题,还是仅仅是我在同一台机器(我的本地PC)上运行客户端和服务器的问题?

有人在我的代码中看到了错误吗?

Edit2:如上所述在EC2实例上它可以工作,但是如果我使用netstat,它仍会显示很多行TIME_WAIT

以下是截图:

https://drive.google.com/file/d/0BzERdJrwWrNCWjhReGhpR2FBMUU/view?usp=sharing

https://drive.google.com/file/d/0BzERdJrwWrNCOG1TWGo5YmxlaTg/view?usp=sharing

第一个截图来自windows。 " WARTEND"意味着"等待" (这是德国人)。

第二个屏幕截图来自Amazon EC2(客户端机器左侧,服务器机器右侧)。

1 个答案:

答案 0 :(得分:3)

两端连接关闭后,进入TIME-WAIT。出于数据完整性原因,它会持续几分钟。

如果缓冲区问题是由服务器上的TIME-WAIT状态引起的,那么解决方案是使服务器成为首先接收关闭的对等体。这将把TIME-WAIT状态转移到客户端,在那里它是良性的。

您可以通过将服务器端请求处理放入循环来实现这一点,这样它就可以处理每个连接的多个请求,并且服务器只有当它到达流的末尾时才关闭套接字。

for (;;)
{
    try
    {
        ClientRequest clientRequest = (ClientRequest) inStream.readObject();
        ...
        outputStream.writeObject(serverResponse);
        outputStream.flush();
    }
    catch (EOFException exc)
    {
        break;
    }
}

如果您在客户端实现连接池,则会大量减少连接数,这将进一步降低缓冲区问题的发生率。