Java套接字:没有可用的缓冲区空间(已达到最大连接数?) [英] Java Sockets: No buffer space available (maximum connections reached?)

查看:372
本文介绍了Java套接字:没有可用的缓冲区空间(已达到最大连接数?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个大问题.我已经开发了一个客户端服务器应用程序.客户端线程将序列化的对象发送到服务器,并且服务器将序列化的对象发送回.当前,我正在使用一台服务器和10个客户端线程,大约30秒后,我从每个客户端线程(IOException)收到错误消息:

I have a big problem. I have developped a client-server application. A client thread sends a serialized object to the server and the server sends back a serialized object. Currently I'm using one server and 10 client threads and after about 30 seconds I get the error message from each client thread (IOException):

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

No buffer space available (maximum connections reached?): connect

如果我正在查看netstat,那么我会看到创建了许多连接,并且该连接正在不断增长,并且所有连接都处于TIME_WAIT状态.

If I'm looking in netstat then I see that there are a lot of connections created and it is growing and growing and all connections are in TIME_WAIT state.

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

I don't know why. I close the sockets in the server and in the clients everytime in a finally block. Here is some code:

在服务器中,我在socketHandlerThread中:

In the server I have in socketHandlerThread:

ServerSocket serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(5000);
while(true) {
       Socket socket = serverSocket.accept();
}

然后将新的套接字放在LinkedBlockingQueue上,然后工作线程获取该套接字并进行以下操作:

The new socket is then put on a LinkedBlockingQueue and a worker thread takes the socket and makes the following:

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();
                }
}

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

On the client side I have the following code:

    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();
            }
   }

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

Can somebody help? I really don't know what mistake I made. I seems that the sockets get no closed but I don't know why.

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

Could it be the problem that I put the sockets on a queue on the server side so that the socket is somehow copied?

如果我将客户端和服务器分别放在运行Linux AMI的不同Amazon EC2经典实例上,那么它将起作用.可能是Windows出现问题,还是仅仅是我在同一台计算机(本地PC)上运行客户端和服务器?

If I put the client and the server each on a different Amazon EC2 classic instance running Linux AMI then it works. Could it be a problem with Windows or is the problem simply that I was running the Clients and servers on the same machine (my local pc)?

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

Does somebody see a bug in my code?

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

As said above on EC2 instances it works but if I use netstat it shows still a lot of lines saying TIME_WAIT.

以下是屏幕截图:

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

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

第一个屏幕截图来自Windows. "WARTEND"的意思是"WAITING"(等待)(德语).

First screenshot is from windows. "WARTEND" means "WAITING" (it is german).

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

The second screenshot is from Amazon EC2 (to the left the client machine, to the right the server machine).

推荐答案

连接结束后,输入 TIME-WAIT.出于数据完整性的原因,它持续了几分钟.

TIME-WAIT is entered after the connection is closed at both ends. It lasts for a couple of minutes, for data integrity reasons.

如果缓冲区问题是由于服务器上的TIME-WAIT状态引起的,则解决方案是使服务器成为最先收到关闭消息的对等方.这样会将TIME-WAIT状态转移到良性的客户端.

If the buffer problem is due to TIME-WAIT states at the server, the solution is to make the server be the peer that first receives the close. That will shift the TIME-WAIT state to the client, where it is benign.

您可以通过将服务器端请求处理放入循环中来做到这一点,这样它就可以处理每个连接的多个请求,从而使服务器仅在套接字到达其流的末端时才关闭套接字.

You can do that by putting your server-side request handling into a loop, so that it can handle multiple requests per connection, and so that the server only closes the socket when it reaches end of stream on it.

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

如果然后在客户端实现连接池,则将大大减少连接数,这将进一步减少缓冲区问题的发生.

If you then implement connection-pooling at the client, you will massively reduce the number of connections, which will further reduce the incidence of the buffer problem.

这篇关于Java套接字:没有可用的缓冲区空间(已达到最大连接数?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆