Socket do Java... estranho, alguem tem uma dica? :S

Pessoal boa tarde,

Eu estava vendo no google um exemplo de PortScanner em Java, e o que mais tem são exemplos explicando como criar, a idéia da maioria das pessoas que publicaram o tutorial é a seguinte:

Cria um objeto socket passando o IP e a porta dentro de um bloco try caso conecte feche o socket se não a exceção é tratada. Mais ou menos assim:

 for(int i=startPortRange; i <=stopPortRange; i++)
       {
                        try
                       {
                        Socket ServerSok = new Socket("127.0.0.1", i);

                 System.out.println("Port in use: " + i );

                        ServerSok.close();
                      }
                catch (Exception e)
                       {
                       }
        System.out.println("Port not in use: " + i );
       }

No entanto acho que isto esta errado pois testando aqui ate IP que não existe ele fala que a porta esta em uso hehe.

Daí tive a seguinte idéia, criei um objeto socket e um DataInputSream que se conectado vai receber alguma resposta da máquina.(ou pelo menos deveria).
Vejam:


        try {

            Socket clientSocket = new Socket("127.0.0.1", 2020);
            clientSocket.setSoTimeout(3000);

            DataInputStream inFromServer = new DataInputStream(clientSocket.getInputStream());

            // O problema esta aqui :(
            System.out.println(""+inFromServer.readInt());

            clientSocket.close();


        } catch (SocketTimeoutException ex) {
            System.out.println("Limite excedido");
        } catch (ConnectException ex) {
            System.out.println("Porta fechada");
        } catch (IOException e) {
            System.out.println("Nao conecta");
        }

    }

O problema esta nessa linha:

Pq tipo se não conectar atinge o limite de tempo pq como não conecta nao tem como ele receber nada da máquina, mas quando conecta ele fica preso nessa linha pois pelo que entendi a maquina não manda nenhuma mensagem pra ele, e ele fica la esperando mesmo com a porta aberta acaba atingindo o tempo limite e não tem como eu fazer a ação dizendo “Porta Aberta”.

Alguém sabe como posso corrigir isso, e se em Java tem uma classe melhor que não seja socket pra eu fazer isso?

Obrigado a todos!

Da uma olhada nesse link:

http://tutorials.jenkov.com/java-nio/channels.html

[quote=vcsmetallica]Da uma olhada nesse link:

http://tutorials.jenkov.com/java-nio/channels.html[/quote]

Mano achei ate interessante a sua dica, o problema é que a maioria dos exemplos que achei nao funcionam ou fazem a mesma coisa que o Socket normal, por exemplo achei esse codigo:


import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(1024);
    SocketChannel sChannel = SocketChannel.open();
    sChannel.configureBlocking(false);
    sChannel.connect(new InetSocketAddress("hostName", 12345));

    int numBytesRead = sChannel.read(buf);

    if (numBytesRead == -1) {
      sChannel.close();
    } else {
      buf.flip();
    }
  }
}

So que nao funciona toda hora cai numa exceção “NotYetConnectedException” nao sei o motivo…
Que tenso…

[quote=tunai]Pessoal boa tarde,

Eu estava vendo no google um exemplo de PortScanner em Java, e o que mais tem são exemplos explicando como criar, a idéia da maioria das pessoas que publicaram o tutorial é a seguinte:

Cria um objeto socket passando o IP e a porta dentro de um bloco try caso conecte feche o socket se não a exceção é tratada. Mais ou menos assim:

 for(int i=startPortRange; i <=stopPortRange; i++)
       {
                        try
                       {
                        Socket ServerSok = new Socket("127.0.0.1", i);

                 System.out.println("Port in use: " + i );

                        ServerSok.close();
                      }
                catch (Exception e)
                       {
                       }
        System.out.println("Port not in use: " + i );
       }

No entanto acho que isto esta errado pois testando aqui ate IP que não existe ele fala que a porta esta em uso hehe.

Daí tive a seguinte idéia, criei um objeto socket e um DataInputSream que se conectado vai receber alguma resposta da máquina.(ou pelo menos deveria).
Vejam:


        try {

            Socket clientSocket = new Socket("127.0.0.1", 2020);
            clientSocket.setSoTimeout(3000);

            DataInputStream inFromServer = new DataInputStream(clientSocket.getInputStream());

            // O problema esta aqui :(
            System.out.println(""+inFromServer.readInt());

            clientSocket.close();


        } catch (SocketTimeoutException ex) {
            System.out.println("Limite excedido");
        } catch (ConnectException ex) {
            System.out.println("Porta fechada");
        } catch (IOException e) {
            System.out.println("Nao conecta");
        }

    }

O problema esta nessa linha:

Pq tipo se não conectar atinge o limite de tempo pq como não conecta nao tem como ele receber nada da máquina, mas quando conecta ele fica preso nessa linha pois pelo que entendi a maquina não manda nenhuma mensagem pra ele, e ele fica la esperando mesmo com a porta aberta acaba atingindo o tempo limite e não tem como eu fazer a ação dizendo “Porta Aberta”.

Alguém sabe como posso corrigir isso, e se em Java tem uma classe melhor que não seja socket pra eu fazer isso?

Obrigado a todos!
[/quote]

Antes de ler sobre Sockets eu sugiro que você leia antes sobre Threads e o pacote padrão de I/O em Java. O seu programa “trava” porque ele está esperando algum dado para ler. A entrada/saída padrão do Java funciona dessa maneira. Quando uma thread pede uma operação de I/O ele bloqueia a thread até que a operação seja completada. Quando o SO sinaliza que a operação foi concluída, a thread volta a executar. Para que o seu programa funcione, basta levantar um servidor que transmita um número inteiro, e você vai ver que o programa não fica travado.

Então cara mais aí que está, pq a idéia é eu verificar se uma determinada porta está aberta na máquina por exemplo supondo que testei a porta 21 no ip localhost. Quando ela nao conecta esse método read me retorna o valor inteiro -1. Só que a porta 21 é de ftp e eu não tenho controle sobre o servidor de ftp e pelo que me parece o socket e o servidor ftp não estão falando a mesma língua pois quando o socket conecta na porta 21 o servidor não envia nada pra ele… esse que está sendo meu maior problema, identificar quando realmente conectou.

Tente o método isConnected():

  Socket s = new Socket(host, port);

  if( s.isConnected() ){
     // faz o que você precisa ....
  }

O método tradicional de se fazer um port scan em qualquer linguagem normalmente não é o de ficar tentando abrir sockets TCP na porta X (isso além de ser lento, pode acabar disparando uma regra de firewall que percebe esse tipo de comportamento).

Olhe os métodos de se fazer um port scan:

[quote=rmendes08]Tente o método isConnected():

[code]
Socket s = new Socket(host, port);

if( s.isConnected() ){
// faz o que você precisa …
}
[/code][/quote]

Por isso eu disse que o socker do java é estranho tentei fazer isso que vc fez, só que eu colocando ate host que nao existe como “1.1.1.1” ele dá que está conectado… estranho²²

Agora, vou seguir sua recomendação e procurar outra maneira peguei essa ideia com sockets pq achei varios tutoriais na internet usando este artifício.

Obrigado pela atenção de vcs, se tiverem mais idéias é so falar ; )