Socket - Muitos arquivos abertos

Oi pessoal.
Alguém poderia me ajudar com o seguinte problema?
Tenho uma aplicação no linux que utiliza sockets e esta recebe um grande número de conexões. Percebi que existem muitos arquivos abertos na máquina (file descriptors), por causa dessa aplicação, fazendo com que a máquina fique instável e sobrecarregada. Não entendo porque isso está acontecendo, porque sempre que abro um socket executo um close().
Já tentei até modificar a propriedade SO_LINGER com o setSoLinger(true, 0), mesmo assim o problema continua a acontecer
Alguém tem uma dica?
Isso pode ser alguma incompatibilidade da JVM com o kernel do linux?

código:

socket.setSoLinger(true, 0);
try
{
socket.close();
//TODO: Verificar se o file descriptor do socket foi fechado.
}
catch(IOException e)
{
//TODO: Verificar se o file descriptor do socket foi fechado.
}

Não dá pra criar uma aplicação que estabeleça a conexão, e rode na máquina servidora. E as clientes utilizarem desta conexão, enquanto ela rodar na máquina servidora?

Desculpe Tiago, mas não entendi. você poderia explicar?
Obrigado.

dá uma olhada neste aki http://www.sumersoft.com/publicacoes/SocketsEmJAVA.pdf
lembrando que o socket deve ser fechado tanto do lado do cliente quanto do servidor.
Use um finally após o try, para garantir que a conexão será encerrada

Ok Tiago. Fiz isso. Vou detalhar o problema:
Quando executamos um socket.close() ele não fecha imediatamente a conexão, pois ainda haverá uma negociação entre o cliente e o servidor. De acordo com o protocolo TCP até o término da conexão deverão acontecer “dois apertos de mãos” entre cliente e servidor, mudando o status da conexão (ver em netstat ) até que esta chegue em CLOSED. Para que essa negociação não aconteça modificamos a opção SO_LINGER para socket.setSoLinger(true, 0), tal modificação implica que nenhum rebebimento ou envio pode ser emitido no socket e ao fechar o socket, posteriormente com o close(), assegura-se que a conexão é fechada e o buffer limpo.
Isso funcionou na aplicação, porém ao colocá-la em produção em um ambiente de milhares de usuários, percebeu-se que o problema ainda está acontecendo. Já procurei por falhas no código e nada.
Gostaria de saber se é algo relacionado com JMV/Linux ou se existe mais opções relacionadas a sockets que podem resolver esse problema.

Como você verificou esse grande número de file descriptors abertos?

Isso é relativamente fácil - existe um comando do Linux que permite verificar isso, que é o lsof

Galera essa aplicação se comunica com outra através de sockets, notei que quando o socket tenta fechar channel.socket().shutdownOutput() ele dispara a seguinte exceção:
finally
{
if (channel != null && channel.socket() != null)
{
channel.socket().shutdownOutput();
}
}

java.net.SocketException: Ponto final de transporte não está conectado
at sun.nio.ch.SocketChannelImpl.shutdown(Native Method)
at sun.nio.ch.SocketChannelImpl.shutdownOutput(SocketChannelImpl.java:651)
at sun.nio.ch.SocketAdaptor.shutdownOutput(SocketAdaptor.java:368)

Essa pode ser a causa do problema?

quando vejo as conexões com o netstat -na vejo que todas são fechadas corretamente na porta de destino, mas existem muitas com uma notação estranha (sem portas). como essa:
unix 2 [ ] STREAM CONECTADO 13130040

Com o lsof | grep java | wc -l vejo que o número de arquivos abertos crescem muito rápido até ultrapassarem o limite da máquina (/proc/sys/fs/file-max).

quando entro em /proc/pid_da_aplicação/fd e listo os filedescriptors vejo que existem muitos FDs que não são “nada”. quando dou um ls -ilhas aparece algo do tipo:
15 -> socket:[142087]
(…varios FDs.)
se eu der um cat 15 aparece isso:
cat: 15: Dispositivo ou endereço inexistente

Alguém já passou por um problema semelhante?
vlw!