fluxo de tomada / saída java escreve: eles bloquear?

votos
31

Se eu só estou escrevendo para um soquete em um fluxo de saída, que isso nunca irá bloquear? Apenas lê pode bloquear, certo? Alguém me disse que escreve pode bloquear, mas eu só ver um recurso de tempo limite para o método de leitura de um socket - Socket.setSoTimeout().

Não faz sentido para mim que uma gravação poderia bloquear.

Publicado 27/08/2009 em 05:44
fonte usuário
Em outras línguas...                            


2 respostas

votos
45

A gravação em um soquete pode bloquear também, especialmente se for um TCP Socket. O sistema operacional somente tampão uma certa quantidade de dados untransmitted (ou transmitidos mas não reconhecidos). Se você escrever coisas mais rápido do que o aplicativo remoto é capaz de lê-lo, a tomada acabará backup e suas writechamadas irá bloquear.

Respondendo a estas perguntas de acompanhamento:

Então, há um mecanismo para definir um tempo limite para isso? Eu não tenho certeza do que o comportamento que teria ... talvez jogar fora dados se buffers estão cheios? Ou, eventualmente, eliminar os dados mais antigos no buffer?

Não há nenhum mecanismo para definir um tempo limite de gravação em um java.net.Socket. Há um Socket.setSoTimeout()método, mas afeta accept()e read()chama ... e nãowrite() chamadas. Aparentemente, você pode obter escrever o tempo limite se você usar NIO, modo sem bloqueio, e um seletor, mas isso não é tão útil como você pode imaginar.

Uma pilha TCP devidamente implementado não descarta dados em buffer a menos que a conexão é fechada. No entanto, quando você começa um tempo de espera de gravação, é incerto se os dados que estão atualmente nos buffers de nível OS foi recebida pela outra extremidade ... ou não. O outro problema é que você não sabe o quanto os dados de seu passado writefoi realmente transferido para de nível OS buffers pilha TCP. Na ausência de algum protocolo de nível de aplicativo para resyncing o fluxo * , a única coisa segura a fazer depois de um tempo limite no writeé desligar a ligação.

Por outro lado, se você usar um socket UDP, write()chamadas não vai bloquear por qualquer período de tempo significativo. Mas a desvantagem é que, se existem problemas de rede ou o aplicativo remoto não está acompanhando, as mensagens serão caiu no chão com nenhuma notificação para cada extremidade. Além disso, você pode achar que as mensagens são por vezes entregue ao aplicativo remoto fora de ordem. Caberá a você (desenvolvedor) para lidar com estas questões.

* É teoricamente possível fazer isso, mas para a maioria dos aplicativos não faz sentido para implementar um mecanismo de ressincronização adicional em cima de um já confiável (a um ponto) fluxo TCP / IP. E se isso fazia sentido, você também precisa lidar com a possibilidade de que a conexão fechada ... por isso seria mais simples de assumir -lo fechado.

Respondeu 27/08/2009 em 06:04
fonte usuário

votos
7

A única maneira de fazer isso é usar NIO e seletores.

Veja o writeup do engenheiro da Sun / Oracle neste relatório bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4031100

Respondeu 15/07/2011 em 16:09
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more