Java - Redes
O termo programação de rede refere-se a escrever programas que são executados em vários dispositivos (computadores), nos quais os dispositivos estão todos conectados uns aos outros usando uma rede.
O pacote java.net das APIs J2SE contém uma coleção de classes e interfaces que fornecem os detalhes de comunicação de baixo nível, permitindo que você escreva programas que se concentrem na solução do problema em questão.
O pacote java.net fornece suporte para os dois protocolos de rede comuns -
-
TCP − TCP significa Transmission Control Protocol, que permite uma comunicação confiável entre dois aplicativos. O TCP é normalmente usado pelo Protocolo da Internet, conhecido como TCP/IP.
-
UDP − UDP significa User Datagram Protocol, um protocolo sem conexão que permite que pacotes de dados sejam transmitidos entre aplicativos.
Este capítulo dá uma boa compreensão sobre os dois seguintes assuntos -
-
Programação de soquete − Este é o conceito mais utilizado em Networking e foi explicado em muito detalhe.
-
Processamento de URL − Isso seria coberto separadamente. Clique aqui para saber mais sobre Processamento de URL na linguagem Java.
Programação de soquete
Os soquetes fornecem o mecanismo de comunicação entre dois computadores usando TCP. Um programa cliente cria um soquete em sua extremidade da comunicação e tenta conectar esse soquete a um servidor.
Quando a conexão é feita, o servidor cria um objeto socket no final da comunicação. O cliente e o servidor agora podem se comunicar escrevendo e lendo no soquete.
A classe java.net.Socket representa um soquete, e a classe java.net.ServerSocket fornece um mecanismo para o programa servidor escutar clientes e estabelecer conexões com eles.
As etapas a seguir ocorrem ao estabelecer uma conexão TCP entre dois computadores usando soquetes -
-
O servidor instancia um objeto ServerSocket, indicando em qual número de porta a comunicação deve ocorrer.
-
O servidor invoca o método accept() da classe ServerSocket. Este método espera até que um cliente se conecte ao servidor na porta especificada.
-
Após o servidor estar esperando, um cliente instancia um objeto Socket, especificando o nome do servidor e o número da porta à qual se conectar.
-
O construtor da classe Socket tenta conectar o cliente ao servidor especificado e ao número da porta. Se a comunicação for estabelecida, o cliente agora possui um objeto Socket capaz de se comunicar com o servidor.
-
No lado do servidor, o método accept() retorna uma referência a um novo soquete no servidor que está conectado ao soquete do cliente.
Depois que as conexões são estabelecidas, a comunicação pode ocorrer usando fluxos de E/S. Cada soquete tem um OutputStream e um InputStream. O OutputStream do cliente está conectado ao InputStream do servidor e o InputStream do cliente está conectado ao OutputStream do servidor.
O TCP é um protocolo de comunicação bidirecional, portanto, os dados podem ser enviados em ambos os fluxos ao mesmo tempo. A seguir estão as classes úteis que fornecem um conjunto completo de métodos para implementar soquetes.
Métodos da classe ServerSocket
O java.net.ServerSocket A classe é usada por aplicativos de servidor para obter uma porta e ouvir solicitações de clientes.
A classe ServerSocket tem quatro construtores -
Nº Sr. | Método e descrição |
---|---|
1 | public ServerSocket(int port) lança IOException Tenta criar um soquete de servidor vinculado à porta especificada. Uma exceção ocorre se a porta já estiver vinculada por outro aplicativo. |
2 | public ServerSocket(int port, int backlog) lança IOException Semelhante ao construtor anterior, o parâmetro backlog especifica quantos clientes de entrada armazenar em uma fila de espera. |
3 | public ServerSocket(porta int, backlog int, endereço InetAddress) lança IOException Semelhante ao construtor anterior, o parâmetro InetAddress especifica o endereço IP local ao qual associar. O InetAddress é usado para servidores que podem ter vários endereços IP, permitindo que o servidor especifique em quais de seus endereços IP aceitar solicitações de clientes. |
4 | public ServerSocket() lança IOException Cria um soquete de servidor não acoplado. Ao usar esse construtor, use o método bind() quando estiver pronto para vincular o soquete do servidor. |
Se o construtor ServerSocket não lançar uma exceção, isso significa que seu aplicativo foi vinculado com êxito à porta especificada e está pronto para solicitações do cliente.
A seguir estão alguns dos métodos comuns da classe ServerSocket -
Nº Sr. | Método e descrição |
---|---|
1 | public int getLocalPort() Retorna a porta na qual o soquete do servidor está escutando. Este método é útil se você passou 0 como o número da porta em um construtor e deixou o servidor encontrar uma porta para você. |
2 | public Socket accept() lança IOException Aguarda um cliente de entrada. Esse método é bloqueado até que um cliente se conecte ao servidor na porta especificada ou o soquete expire, assumindo que o valor de tempo limite foi definido usando o método setSoTimeout(). Caso contrário, este método bloqueia indefinidamente. |
3 | public void setSoTimeout(int timeout) Define o valor de tempo limite para quanto tempo o soquete do servidor espera por um cliente durante o accept(). |
4 | public void bind(SocketAddress host, int backlog) Vincula o soquete ao servidor e porta especificados no objeto SocketAddress. Use este método se você tiver instanciado o ServerSocket usando o construtor sem argumentos. |
Quando o ServerSocket invoca accept(), o método não retorna até que um cliente se conecte. Depois que um cliente se conecta, o ServerSocket cria um novo Socket em uma porta não especificada e retorna uma referência a esse novo Socket. Uma conexão TCP agora existe entre o cliente e o servidor, e a comunicação pode começar.
Métodos de classe de soquete
O java.net.Socket A classe representa o soquete que o cliente e o servidor usam para se comunicarem. O cliente obtém um objeto Socket instanciando um, enquanto o servidor obtém um objeto Socket a partir do valor de retorno do método accept().
A classe Socket tem cinco construtores que um cliente usa para se conectar a um servidor -
Nº Sr. | Método e descrição |
---|---|
1 | public Socket(String host, int port) lança UnknownHostException, IOException. Este método tenta se conectar ao servidor especificado na porta especificada. Se esse construtor não lançar uma exceção, a conexão será bem-sucedida e o cliente será conectado ao servidor. |
2 | public Socket(host InetAddress, porta int) lança IOException Esse método é idêntico ao construtor anterior, exceto que o host é indicado por um objeto InetAddress. |
3 | public Socket(String host, int port, InetAddress localAddress, int localPort) lança IOException. Conecta-se ao host e porta especificados, criando um soquete no host local no endereço e porta especificados. |
4 | public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) lança IOException. Esse método é idêntico ao construtor anterior, exceto que o host é indicado por um objeto InetAddress em vez de um String. |
5 | Soquete público() Cria um soquete desconectado. Use o método connect() para conectar este soquete a um servidor. |
Quando o construtor Socket retorna, ele não instancia simplesmente um objeto Socket, mas na verdade tenta se conectar ao servidor e à porta especificados.
Alguns métodos de interesse na classe Socket estão listados aqui. Observe que tanto o cliente quanto o servidor têm um objeto Socket, portanto, esses métodos podem ser invocados pelo cliente e pelo servidor.
Nº Sr. | Método e descrição |
---|---|
1 | public void connect(SocketAddress host, int timeout) lança IOException Este método conecta o soquete ao host especificado. Esse método é necessário apenas quando você instancia o Socket usando o construtor sem argumento. |
2 | public InetAddress getInetAddress() Esse método retorna o endereço do outro computador ao qual esse soquete está conectado. |
3 | public int getPort() Retorna a porta à qual o soquete está vinculado na máquina remota. |
4 | public int getLocalPort() Retorna a porta à qual o soquete está vinculado na máquina local. |
5 | público SocketAddress getRemoteSocketAddress() Retorna o endereço do soquete remoto. |
6 | public InputStream getInputStream() lança IOException Retorna o fluxo de entrada do soquete. O fluxo de entrada é conectado ao fluxo de saída do soquete remoto. |
7 | Public OutputStream getOutputStream() lança IOException Retorna o fluxo de saída do soquete. O fluxo de saída é conectado ao fluxo de entrada do soquete remoto. |
8 | public void close() lança IOException Fecha o soquete, o que faz com que este objeto Socket não seja mais capaz de se conectar novamente a qualquer servidor. |
Métodos de classe InetAddress
Essa classe representa um endereço IP (Internet Protocol). Aqui estão os seguintes métodos úteis que você precisaria ao fazer a programação de soquete -
Nº Sr. | Método e descrição |
---|---|
1 | estático InetAddress getByAddress(byte[] addr) Retorna um objeto InetAddress dado o endereço IP bruto. |
2 | estático InetAddress getByAddress(String host, byte[] addr) Cria um InetAddress com base no nome do host e no endereço IP fornecidos. |
3 | estático InetAddress getByName(String host) Determina o endereço IP de um host, dado o nome do host. |
4 | String getHostAddress() Retorna a string do endereço IP na apresentação textual. |
5 | String getHostName() Obtém o nome do host para este endereço IP. |
6 | estático InetAddress InetAddress getLocalHost() Retorna o host local. |
7 | String toString() Converte este endereço IP em uma String. |
Exemplo de cliente de soquete
O GreetingClient a seguir é um programa cliente que se conecta a um servidor usando um soquete, envia uma saudação e aguarda uma resposta.
Exemplo
// File Name GreetingClient.java import java.net.*; import java.io.*; public class GreetingClient { public static void main(String [] args) { String serverName = args[0]; int port = Integer.parseInt(args[1]); try { System.out.println("Connecting to " + serverName + " on port " + port); Socket client = new Socket(serverName, port); System.out.println("Just connected to " + client.getRemoteSocketAddress()); OutputStream outToServer = client.getOutputStream(); DataOutputStream out = new DataOutputStream(outToServer); out.writeUTF("Hello from " + client.getLocalSocketAddress()); InputStream inFromServer = client.getInputStream(); DataInputStream in = new DataInputStream(inFromServer); System.out.println("Server says " + in.readUTF()); client.close(); } catch (IOException e) { e.printStackTrace(); } } }
Exemplo de servidor de soquete
O programa GreetingServer a seguir é um exemplo de um aplicativo de servidor que usa a classe Socket para escutar clientes em um número de porta especificado por um argumento de linha de comando -
Exemplo
// File Name GreetingServer.java import java.net.*; import java.io.*; public class GreetingServer extends Thread { private ServerSocket serverSocket; public GreetingServer(int port) throws IOException { serverSocket = new ServerSocket(port); serverSocket.setSoTimeout(10000); } public void run() { while(true) { try { System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "..."); Socket server = serverSocket.accept(); System.out.println("Just connected to " + server.getRemoteSocketAddress()); DataInputStream in = new DataInputStream(server.getInputStream()); System.out.println(in.readUTF()); DataOutputStream out = new DataOutputStream(server.getOutputStream()); out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress() + "\nGoodbye!"); server.close(); } catch (SocketTimeoutException s) { System.out.println("Socket timed out!"); break; } catch (IOException e) { e.printStackTrace(); break; } } } public static void main(String [] args) { int port = Integer.parseInt(args[0]); try { Thread t = new GreetingServer(port); t.start(); } catch (IOException e) { e.printStackTrace(); } } }
Compile o cliente e o servidor e inicie o servidor da seguinte forma -
$ java GreetingServer 6066 Waiting for client on port 6066...
Verifique o programa cliente da seguinte forma -
Saída
$ java GreetingClient localhost 6066 Connecting to localhost on port 6066 Just connected to localhost/127.0.0.1:6066 Server says Thank you for connecting to /127.0.0.1:6066 Goodbye!
Java