Definir um tempo limite para operações de soquete

86

Quando eu crio um soquete:

Socket socket = new Socket(ipAddress, port);

Ele lança uma exceção, que está OK, porque o endereço IP não está disponível. (As variáveis ​​de teste onde String ipAddress = "192.168.0.3"e int port = 300.)

O problema é: como faço para definir o tempo limite para esse soquete?

Quando eu crio o soquete, como reduzo o tempo antes de obter um UnknownHostExceptione fazer com que o soquete atinja o tempo limite?

Jennifer
fonte
10
@adrianboimvaser: Nesse caso, você deve sinalizar como uma duplicata e deixar um comentário apontando para a duplicata, para que um moderador possa fechá-la como tal (você deixou esse comentário há um ano - talvez você já saiba disso). Eu votaria por fazer isso agora, mas não tenho ideia de onde está a duplicata!
Tom Anderson,
1
Para continuar a tendência de responder com anos de atraso, @EJP o título desta pergunta é muito menos ambíguo do que a duplicata que você sugeriu
Isaac
@Isaac E na verdade não é uma duplicata, comentário retratado.
Marquês de Lorne,
(Nota: ajustei o título para ficar menos ambíguo.)
Stephen C de

Respostas:

165

Use o Socket()construtor e o connect(SocketAddress endpoint, int timeout)método .

No seu caso, seria algo como:

Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, port), 1000);

Citando da documentação

connect

public void connect(SocketAddress endpoint, int timeout) throws IOException

Conecta este soquete ao servidor com um valor de tempo limite especificado. Um tempo limite de zero é interpretado como um tempo limite infinito. A conexão será então bloqueada até ser estabelecida ou ocorrer um erro.

Parâmetros:

endpoint- o SocketAddress
timeout- o valor de tempo limite a ser usado em milissegundos.

Lança:

IOException- se ocorrer um erro durante a conexão
SocketTimeoutException- se o tempo limite expirar antes de conectar
IllegalBlockingModeException- se este soquete tiver um canal associado, e o canal estiver no modo sem bloqueio
IllegalArgumentException- se o endpoint for nulo ou for uma subclasse SocketAddress não suportada por este soquete

Desde: 1.4

aioobe
fonte
4
Isso pode reduzir o tempo limite de ConnectException (mas não aumentá-lo) e não tem efeito no tempo limite de UnknownHostException, que o OP afirma estar recebendo (embora eu não acredite). Observe também que o Javadoc está incorreto ao declarar que o padrão é infinito. Não é. A plataforma tem um tempo limite padrão de cerca de um minuto e não pode ser aumentado.
Marquês de Lorne
3
Mesmo depois de 4 anos, isso foi útil, esta deve ser a resposta aceita.
Sharp Edge
4
Já se passaram 5 anos e é a melhor resposta que encontrei na Internet. Obrigado
MBH
1
Também é importante solicitar socket.setSoTimeout(timeoutMillis)tempos limite durante o bloqueio de operações de E / S.
Gray
43

Você não define um tempo limite para o soquete, você define um tempo limite para as operações executadas naquele soquete.

Por exemplo socket.connect(otherAddress, timeout)

Ou socket.setSoTimeout(timeout)para definir um tempo limite nas read()operações.

Veja: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html

Payne
fonte
Bem, neste caso também é uma operação, conectando. Não consigo encontrar nenhum lugar que afirme que este ctor usa um tempo limite infinito, embora pareça ser o caso.
sandos
3
@sandos É claramente declarado no Javadoc para connect (). No entanto, também está incorreto. O tempo limite padrão é o tempo limite da plataforma, em torno de um minuto, não infinito, e só pode ser reduzido por este método connect (), não aumentado.
Marquês de Lorne
note, socket.setSoTimeoutdeve ser chamado DEPOIS connectou não terá efeito e as leituras nunca expirarão. este é um problema mal documentado.
pstanton 01 de
19

Você pode usar a seguinte solução:

SocketAddress sockaddr = new InetSocketAddress(ip, port);
// Create your socket
Socket socket = new Socket();
// Connect with 10 s timeout
socket.connect(sockaddr, 10000);

Espero que ajude!

recife
fonte
1
Se, como ele afirma, estiver recebendo um UnknownHostException, isso acontecerá na primeira linha, onde não há nenhum tempo limite modificado em vigor.
Marquês de Lorne
No entanto, a primeira linha não lança nenhuma exceção. Da documentação: "Será feita uma tentativa de resolver o nome do host em um InetAddress. Se essa tentativa falhar, o endereço será sinalizado como não resolvido"
ady
Nesse caso, será resolvido pelo connect()método, mas não sob o controle de um tempo limite.
Marquês de Lorne
8

Você não pode controlar o tempo limite devido a UnknownHostException . Estes são tempos de DNS. Você só pode controlar o tempo limite de conexão em um host válido. Nenhuma das respostas anteriores aborda esse ponto corretamente.

Mas acho difícil acreditar que você está realmente recebendo um UnknownHostException quando especifica um endereço IP em vez de um nome de host.

EDITAR Para controlar os tempos limite de DNS do Java, consulte esta resposta .

Marquês de Lorne
fonte