Como criar um aplicativo de rede em Java (com imagens)

Índice:

Como criar um aplicativo de rede em Java (com imagens)
Como criar um aplicativo de rede em Java (com imagens)

Vídeo: Como criar um aplicativo de rede em Java (com imagens)

Vídeo: Como criar um aplicativo de rede em Java (com imagens)
Vídeo: LG K41s, K51s, K61 | Como Tirar Print - Foto da Tela (Você Não Sabe Disso? Aprenda Aqui!) 2024, Abril
Anonim

Escrever código que é executado em um determinado dispositivo é muito satisfatório. Mas, escrever código que é executado em vários dispositivos que se comunicam entre si é simplesmente uma afirmação de vida. Este artigo ensinará como conectar e trocar mensagens pela rede usando o protocolo de controle de transmissão (TCP).

Neste artigo, você configurará um aplicativo que conectará seu computador a ele mesmo e, essencialmente, o deixará louco - fale com ele mesmo. Você também aprenderá a diferença entre os dois fluxos mais amplamente usados para rede em Java e como eles funcionam.

Streams de dados e objetos

Antes de mergulhar no código, a diferença entre os dois fluxos usados no artigo precisa ser distinguida.

Streams de dados

Os fluxos de dados processam strings e tipos de dados primitivos. Os dados enviados por fluxos de dados precisam ser serializados e desserializados manualmente, o que torna mais difícil a transferência de dados complexos. Porém, os fluxos de dados podem se comunicar com servidores e clientes escritos em outras linguagens além do Java. Os fluxos brutos são semelhantes aos fluxos de dados nesse aspecto, mas os fluxos de dados garantem que os dados sejam formatados de forma independente da plataforma, o que é benéfico porque ambas as partes poderão ler os dados enviados.

Streams de objetos

Os fluxos de objetos processam tipos de dados primitivos e objetos que implementam

Serializável

interface. Os dados enviados por fluxos de objetos são serializados e desserializados automaticamente, o que facilita a transferência de dados complexos. Porém, os fluxos de objetos só podem se comunicar com servidores e clientes escritos em Java. Também,

ObjectOutputStream

na inicialização, envia um cabeçalho para o

InputStream

da outra parte que, na inicialização, bloqueia a execução até que o cabeçalho seja recebido.

Passos

Crie um aplicativo de rede em Java Step1
Crie um aplicativo de rede em Java Step1

Etapa 1. Crie uma classe

Crie uma classe e nomeie-a como quiser. Neste artigo, ele será nomeado

NetworkAppExample

public class NetworkAppExample {}

Crie um aplicativo de rede em Java Step2
Crie um aplicativo de rede em Java Step2

Etapa 2. Crie um método principal

Crie um método principal e declare que pode lançar exceções de

Exceção

tipo e qualquer subclasse dele - todas as exceções. Isso é considerado uma prática ruim, mas é aceitável para exemplos simples.

public class NetworkAppExample {public static void main (String args) lança exceção {}}

Crie um aplicativo de rede em Java Step3
Crie um aplicativo de rede em Java Step3

Etapa 3. Declare o endereço do servidor

Este exemplo usará o endereço do host local e um número de porta arbitrário. O número da porta deve estar no intervalo de 0 a 65535 (inclusive). No entanto, os números de porta a serem evitados variam de 0 a 1023 (inclusive) porque são portas reservadas do sistema.

public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; }}

Crie um aplicativo de rede em Java Step4
Crie um aplicativo de rede em Java Step4

Etapa 4. Crie um servidor

O servidor está vinculado ao endereço e à porta e escuta as conexões de entrada. Em Java,

ServerSocket

representa o endpoint do lado do servidor e sua função é aceitar novas conexões.

ServerSocket

não possui streams para leitura e envio de dados, pois não representa a conexão entre um servidor e um cliente.

import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); }}

Crie um aplicativo de rede em Java Step5
Crie um aplicativo de rede em Java Step5

Etapa 5. Início do servidor de log

Para fins de registro, imprima no console que o servidor foi iniciado.

import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); }}

Crie um aplicativo de rede em Java Step6
Crie um aplicativo de rede em Java Step6

Etapa 6. Crie um cliente

O cliente está vinculado ao endereço e à porta de um servidor e escuta os pacotes (mensagens) após o estabelecimento da conexão. Em Java,

Soquete

representa um ponto de extremidade do lado do cliente conectado ao servidor ou uma conexão (do servidor) ao cliente e é usado para se comunicar com a parte na outra extremidade.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); }}

Crie um aplicativo de rede em Java Step7
Crie um aplicativo de rede em Java Step7

Etapa 7. Registrar tentativa de conexão

Para fins de registro, imprima no console que a conexão foi tentada.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); }}

Crie um aplicativo de rede em Java Step8
Crie um aplicativo de rede em Java Step8

Etapa 8. Estabeleça a conexão

Os clientes nunca se conectarão a menos que o servidor ouça e aceite, em outras palavras, estabeleça conexões. Em Java, as conexões são estabelecidas usando

aceitar()

método de

ServerSocket

classe. O método bloqueará a execução até que um cliente se conecte.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); }}

Crie um aplicativo de rede em Java Step9
Crie um aplicativo de rede em Java Step9

Etapa 9. Registrar a conexão estabelecida

Para fins de registro, imprima no console que a conexão entre o servidor e o cliente foi estabelecida.

import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); }}

Crie um aplicativo de rede em Java Step10
Crie um aplicativo de rede em Java Step10

Etapa 10. Prepare os fluxos de comunicação

A comunicação é feita por meio de fluxos e, neste aplicativo, fluxos brutos de (conexão de) servidor (para cliente) e cliente precisam ser encadeados a fluxos de dados ou objetos. Lembre-se de que ambas as partes precisam usar o mesmo tipo de fluxo.

  • Streams de dados

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); }}

  • Fluxos de objetos

    Quando vários fluxos de objetos são usados, os fluxos de entrada devem ser inicializados na mesma ordem que os fluxos de saída porque

    ObjectOutputStream

    envia um cabeçalho para a outra parte e

    ObjectInputStream

    bloqueia a execução até ler o cabeçalho.

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); }}

    A ordem especificada no código acima pode ser mais fácil de lembrar - primeiro inicialize os fluxos de saída e, em seguida, os fluxos de entrada na mesma ordem. No entanto, outra ordem de inicialização de fluxos de objetos é a seguinte:

    ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ());

Crie um aplicativo de rede em Java Step11
Crie um aplicativo de rede em Java Step11

Etapa 11. Registre que a comunicação está pronta

Para fins de registro, imprima no console que a comunicação está pronta.

// código omitido import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); // código omitido System.out.println ("A comunicação está pronta."); }}

Crie um aplicativo de rede em Java Step12
Crie um aplicativo de rede em Java Step12

Etapa 12. Crie uma mensagem

Neste aplicativo,

Olá Mundo

o texto será enviado para o servidor como

byte

ou

Fragmento

. Declare uma variável do tipo que depende do fluxo usado. Usar

byte

para fluxos de dados e

Fragmento

para fluxos de objetos.

  • Streams de dados

    Usando fluxos de dados, a serialização é feita convertendo objetos em tipos de dados primitivos ou um

    Fragmento

    . Nesse caso,

    Fragmento

    é convertido para

    byte

    em vez de escrever usando

    writeBytes ()

    método para mostrar como isso seria feito com outros objetos, como imagens ou outros arquivos.

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); byte messageOut = "Hello World".getBytes (); }}

  • Fluxos de objetos

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); String messageOut = "Hello World"; }}

Crie um aplicativo de rede em Java Step13
Crie um aplicativo de rede em Java Step13

Etapa 13. Envie a mensagem

Grave dados no fluxo de saída e libere o fluxo para garantir que os dados foram inteiramente gravados.

  • Streams de dados

    O comprimento de uma mensagem precisa ser enviado primeiro para que a outra parte saiba quantos bytes ela precisa ler. Depois que o comprimento é enviado como um tipo inteiro primitivo, os bytes podem ser enviados.

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}

  • Fluxos de objetos

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); }}

Crie um aplicativo de rede em Java Step14
Crie um aplicativo de rede em Java Step14

Etapa 14. Registrar a mensagem enviada

Para fins de registro, imprima no console que a mensagem foi enviada.

  • Streams de dados

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Mensagem enviada ao servidor:" + nova String (messageOut)); }}

  • Fluxos de objetos

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Mensagem enviada ao servidor:" + messageOut); }}

Crie um aplicativo de rede em Java Step15
Crie um aplicativo de rede em Java Step15

Etapa 15. Leia a mensagem

Leia os dados do fluxo de entrada e converta-os. Uma vez que sabemos exatamente o tipo de dados enviados, iremos criar um

Fragmento

a partir de

byte

ou elenco

Objeto

para

Fragmento

sem verificar, dependendo do fluxo usado.

  • Streams de dados

    Como o comprimento foi enviado primeiro e os bytes depois, a leitura deve ser feita na mesma ordem. Caso o comprimento seja zero, não há nada para ler. O objeto é desserializado quando os bytes são convertidos de volta em uma instância, neste caso, de

    Fragmento

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Mensagem enviada ao servidor:" + nova String (messageOut)); comprimento interno = serverIn.readInt (); if (comprimento> 0) {byte mensagemIn = novo byte [comprimento]; serverIn.readFully (messageIn, 0, messageIn.length); }}}

  • Fluxos de objetos

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Mensagem enviada ao servidor:" + messageOut); String messageIn = (String) serverIn.readObject (); }}

Crie um aplicativo de rede em Java Step16
Crie um aplicativo de rede em Java Step16

Etapa 16. Mensagem de leitura de log

Para fins de registro, imprima no console a mensagem recebida e imprima seu conteúdo.

  • Streams de dados

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Mensagem enviada ao servidor:" + nova String (messageOut)); comprimento interno = serverIn.readInt (); if (comprimento> 0) {byte mensagemIn = novo byte [comprimento]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Mensagem recebida do cliente:" + nova String (messageIn)); }}}

  • Fluxos de objetos

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A comunicação está pronta."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Mensagem enviada ao servidor:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Mensagem recebida do cliente:" + messageIn); }}

Crie um aplicativo de rede em Java Step17
Crie um aplicativo de rede em Java Step17

Etapa 17. Desconecte as conexões

A conexão é desconectada quando uma das partes fecha seus streams. Em Java, ao fechar o fluxo de saída, o soquete associado e o fluxo de entrada também são fechados. Depois que uma parte do outro lado descobre que a conexão está inativa, ela também precisa fechar o fluxo de saída para evitar vazamentos de memória.

// código omitido import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); // código omitido System.out.println ("A comunicação está pronta."); // código omitido clientOut.close (); serverOut.close (); }}

Crie um aplicativo de rede em Java Step18 V2
Crie um aplicativo de rede em Java Step18 V2

Etapa 18. Desconexão de log

Para fins de registro, as conexões de impressão para o console foram desconectadas.

// código omitido import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); // código omitido System.out.println ("A comunicação está pronta."); // código omitido clientOut.close (); serverOut.close (); System.out.println ("Conexões fechadas."); }}

Crie um aplicativo de rede em Java Step19
Crie um aplicativo de rede em Java Step19

Etapa 19. Encerre o servidor

As conexões foram desconectadas, mas o servidor ainda está funcionando. Como

ServerSocket

não está associado a nenhum fluxo, ele precisa ser explicitamente fechado chamando

fechar()

método.

// código omitido import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); // código omitido System.out.println ("A comunicação está pronta."); // código omitido clientOut.close (); serverOut.close (); System.out.println ("Conexões fechadas."); server.close (); }}

Crie um aplicativo de rede em Java Step20
Crie um aplicativo de rede em Java Step20

Etapa 20. Terminação do servidor de log

Para fins de registro, a impressão no servidor do console foi encerrada.

// código omitido import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor ServerSocket = novo ServerSocket (porta, 50, InetAddress.getByName (host)); System.out.println ("Servidor iniciado."); Cliente de soquete = novo soquete (host, porta); System.out.println ("Conectando ao servidor…"); Conexão de soquete = server.accept (); System.out.println ("Conexão estabelecida."); // código omitido System.out.println ("A comunicação está pronta."); // código omitido clientOut.close (); serverOut.close (); System.out.println ("Conexões fechadas."); server.close (); System.out.println ("Servidor encerrado."); }}

Crie um aplicativo de rede em Java Step21
Crie um aplicativo de rede em Java Step21

Etapa 21. Compile e execute

O registro nos permitiu saber se o aplicativo foi bem-sucedido ou não. Saída esperada:

Servidor iniciado. Conectando ao servidor… Conexão estabelecida. A comunicação está pronta. Mensagem enviada ao servidor: Hello World Mensagem recebida do cliente: Hello World Connections encerrado. Servidor encerrado.

Caso sua saída não seja como a anterior, o que é improvável que aconteça, existem algumas soluções:

  • Se a saída parar na linha

    Conexão estabelecida.

    e fluxos de objetos são usados, limpe cada

    ObjectOutputStream

  • imediatamente após a inicialização porque os cabeçalhos, por algum motivo, não foram enviados.
  • Se a saída for impressa

    java.net. BindException: Endereço já em uso

  • escolha um número de porta diferente porque aquele especificado já está em uso.

Pontas

  • A conexão a um servidor em uma rede diferente é feita conectando-se ao endereço IP externo de um dispositivo que executa o servidor que possui uma porta encaminhada.
  • A conexão a um servidor na mesma rede é feita conectando-se ao endereço IP privado de um dispositivo que executa o servidor ou encaminhando uma porta e conectando-se ao endereço IP externo do dispositivo.
  • Existem softwares, como o Hamachi, que permitem a conexão ao servidor em uma rede diferente sem encaminhar uma porta, mas requer a instalação do software em ambos os dispositivos.

Exemplos

Os aplicativos de rede que usam bloqueio de entrada / saída precisam usar threads. Os exemplos a seguir mostram uma implementação minimalista de servidor e cliente com threads. O código de rede é essencialmente o mesmo do artigo, exceto que alguns fragmentos foram sincronizados, movidos para threads e exceções são tratadas.

Server.java

import java.io. IOException; import java.net. InetAddress; import java.net. ServerSocket; import java.net. SocketException; import java.net. UnknownHostException; import java.util. ArrayList; import java.util. Collections; import java.util. List; / ** * A classe {@code Server} representa um ponto de extremidade do servidor em uma rede. {@code Server} uma vez vinculado a um determinado endereço IP * e porta, estabelece conexões com clientes e é capaz de se comunicar com eles ou desconectá-los. *

* Esta classe é threadsafe. * * @ versão 1.0 * @see Client * @see Connection * / public class Server implementa Runnable {private ServerSocket server; lista privada conexões; thread de discussão privada; objeto final privado connectionsLock = new Object (); / ** * Constrói um {@code Server} que interage com clientes no nome de host e porta especificados com o comprimento máximo solicitado * especificado de uma fila de clientes de entrada. * * @param host Endereço do host a ser usado. * @param port Número da porta a ser usada. * @param backlog Comprimento máximo solicitado da fila de clientes de entrada. * @throws NetworkException Se ocorrer um erro ao iniciar um servidor. * / public Server (String host, int port, int backlog) lança NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } catch (UnknownHostException e) {throw new NetworkException ("Nome do host não pôde ser resolvido:" + host, e); } catch (IllegalArgumentException e) {throw new NetworkException ("O número da porta precisa estar entre 0 e 65535 (inclusive):" + porta); } catch (IOException e) {throw new NetworkException ("O servidor não pôde ser iniciado.", e); } conexões = Collections.synchronizedList (new ArrayList ()); thread = novo Thread (este); thread.start (); } / ** * Constrói um {@code Server} que interage com clientes no nome de host e porta especificados. * * @param host Endereço do host a ser vinculado. * @param port Número da porta para vincular. * @throws NetworkException Se ocorrerem erros ao iniciar um servidor. * / public Server (String host, int port) lança NetworkException {this (host, port, 50); } / ** * Escuta, aceita e registra conexões de entrada de clientes. * / @Override public void run () {while (! Server.isClosed ()) {try {connections.add (new Connection (server.accept ())); } catch (SocketException e) {if (! e.getMessage (). equals ("Socket fechado")) {e.printStackTrace (); }} catch (NetworkException | IOException e) {e.printStackTrace (); }}} / ** * Envia dados para todos os clientes cadastrados. * * @param data Dados a serem enviados. * @throws IllegalStateException Se houver tentativa de gravação de dados quando o servidor estiver offline. * @throws IllegalArgumentException Se os dados a serem enviados forem nulos. * / public void broadcast (Object data) {if (server.isClosed ()) {throw new IllegalStateException ("Dados não enviados, servidor está offline."); } if (dados == nulo) {lançar novo IllegalArgumentException ("dados nulos"); } synchronized (connectionsLock) {for (Connection connection: connections) {try {connection.send (data); System.out.println ("Dados enviados ao cliente com sucesso."); } catch (NetworkException e) {e.printStackTrace (); }}}} / ** * Envia uma mensagem de desconexão e desconecta o cliente especificado. * * @param connection Client para desconectar. * @throws NetworkException Se ocorrer um erro ao fechar a conexão. * / public void disconnect (Connection connection) lança NetworkException {if (connections.remove (connection)) {connection.close (); }} / ** * Envia uma mensagem de desconexão a todos os clientes, desconecta-os e encerra o servidor. * / public void close () lança NetworkException {synchronized (connectionsLock) {para (conexão de conexão: conexões) {try {connection.close (); } catch (NetworkException e) {e.printStackTrace (); }}} connections.clear (); tente {server.close (); } catch (IOException e) {throw new NetworkException ("Erro ao fechar o servidor."); } finalmente {thread.interrupt (); }} / ** * Retorna se o servidor está online ou não. * * @return True se o servidor estiver online. Falso, caso contrário. * / public boolean isOnline () {return! server.isClosed (); } / ** * Retorna uma matriz de clientes registrados. * / public Connection getConnections () {synchronized (connectionsLock) {return connections.toArray (new Connection [connections.size ()]); }}}

Client.java

import java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; / ** * A classe {@code Client} representa um ponto de extremidade do cliente em uma rede. {@code Client}, uma vez conectado a um determinado * servidor, tem a garantia de apenas se comunicar com o servidor. Se outros clientes recebem ou não os dados * depende da implementação do servidor. *

* Esta classe é threadsafe. * * @ versão 1.0 * @see Server * @see Connection * / public class Client {private Connection connection; / ** * Constrói um {@code Client} conectado ao servidor no host e na porta especificados. * * @param host Endereço do host a ser vinculado. * @param port Número da porta para vincular. * @throws NetworkException Se ocorrer um erro ao iniciar um servidor. * / public Client (String host, int port) lança NetworkException {try {connection = new Connection (new Socket (host, port)); } catch (UnknownHostException e) {throw new NetworkException ("Nome do host não pôde ser resolvido:" + host, e); } catch (IllegalArgumentException e) {throw new NetworkException ("O número da porta precisa estar entre 0 e 65535 (inclusive):" + porta); } catch (IOException e) {throw new NetworkException ("O servidor não pôde ser iniciado.", e); }} / ** * Envia dados para a outra parte. * * @param data Dados a serem enviados. * @throws NetworkException Se a gravação no fluxo de saída falhar. * @throws IllegalStateException Se a gravação de dados for tentada quando a conexão for fechada. * @throws IllegalArgumentException Se os dados a serem enviados forem nulos. * @throws UnsupportedOperationException Se houver tentativa de envio de tipo de dados sem suporte. * / public void send (Object data) lança NetworkException {connection.send (data); } / ** * Envia uma mensagem de desconexão e fecha a conexão com o servidor. * / public void close () lança NetworkException {connection.close (); } / ** * Retorna se o cliente está ou não conectado ao servidor. * * @return True se o cliente estiver conectado. Falso, caso contrário. * / public boolean isOnline () {return connection.isConnected (); } / ** * Retorna a instância {@link Connection} do cliente. * / conexão pública getConnection () {conexão de retorno; }}

Connection.java

import java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; import java.net. Socket; import java.net. SocketException; / ** * A classe {@code Connection} representa uma conexão do servidor ao cliente ou um ponto final do cliente em uma rede * {@code Connection}, uma vez conectado, é capaz de trocar dados com outra parte ou partes, dependendo em uma implementação de servidor *. *

* Esta classe é threadsafe. * * @ versão 1.0 * @see Server * @see Client * / public class Connection implementa Runnable {private Socket socket; saída de DataOutputStream privada; Private DataInputStream in; thread de discussão privada; objeto final privado writeLock = new Object (); Objeto final privado readLock = new Object (); / ** * Constrói {@code Connection} usando streams de um {@link Socket} especificado. * * @param socket Soquete de onde buscar os streams.* / public Connection (Socket socket) throws NetworkException {if (socket == null) {throw new IllegalArgumentException ("null socket"); } this.socket = socket; experimente {out = new DataOutputStream (socket.getOutputStream ()); } catch (IOException e) {throw new NetworkException ("Não foi possível acessar o fluxo de saída.", e); } tente {in = new DataInputStream (socket.getInputStream ()); } catch (IOException e) {throw new NetworkException ("Não foi possível acessar o fluxo de entrada.", e); } tópico = novo Tópico (este); thread.start (); } / ** * Lê mensagens enquanto a conexão com a outra parte está ativa. * / @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; byte bytes; sincronizado (readLock) {identificador = in.readInt (); comprimento interno = in.readInt (); if (comprimento> 0) {bytes = novo byte [comprimento]; in.readFully (bytes, 0, bytes.length); } else {continue; }} switch (identificador) {case Identifier. INTERNAL: String command = new String (bytes); if (command.equals ("desconectar")) {if (! socket.isClosed ()) {System.out.println ("Pacote de desconexão recebido."); tente {fechar (); } catch (NetworkException e) {return; } } } pausa; Case Identifier. TEXT: System.out.println ("Mensagem recebida:" + nova String (bytes)); pausa; padrão: System.out.println ("Dados não reconhecidos recebidos."); }} catch (SocketException e) {if (! e.getMessage (). equals ("Socket fechado")) {e.printStackTrace (); }} catch (IOException e) {e.printStackTrace (); }}} / ** * Envia dados para a outra parte. * * @param data Dados a serem enviados. * @throws NetworkException Se a gravação no fluxo de saída falhar. * @throws IllegalStateException Se a gravação de dados for tentada quando a conexão for fechada. * @throws IllegalArgumentException Se os dados a serem enviados forem nulos. * @throws UnsupportedOperationException Se houver tentativa de envio de tipo de dados sem suporte. * / public void send (Object data) throws NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Dados não enviados, conexão fechada."); } if (dados == nulo) {lançar novo IllegalArgumentException ("dados nulos"); } identificador interno; byte bytes; if (instância de dados String) {identificador = Identificador. TEXT; bytes = ((String) dados).getBytes (); } else {throw new UnsupportedOperationException ("Tipo de dados não suportado:" + data.getClass ()); } tente {synchronized (writeLock) {out.writeInt (identifier); out.writeInt (bytes.length); out.write (bytes); out.flush (); }} catch (IOException e) {throw new NetworkException ("Os dados não puderam ser enviados.", e); }} / ** * Envia uma mensagem de desconexão e fecha a conexão com a outra parte. * / public void close () lança NetworkException {if (socket.isClosed ()) {lança nova IllegalStateException ("A conexão já está fechada."); } tente {byte mensagem = "desconectar".getBytes (); sincronizado (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (message.length); out.write (mensagem); out.flush (); }} catch (IOException e) {System.out.println ("Mensagem de desconexão não pôde ser enviada."); } tente {synchronized (writeLock) {out.close (); }} catch (IOException e) {throw new NetworkException ("Erro ao fechar a conexão.", e); } finalmente {thread.interrupt (); }} / ** * Retorna se a conexão com a outra parte está ativa ou não. * * @return True se a conexão estiver ativa. Falso, caso contrário. * / public boolean isConnected () {return! socket.isClosed (); }}

Identifier.java

/ ** * A classe {@code Identifier} contém constantes usadas por {@link Connection} para serializar e desserializar os dados * enviados pela rede. * * @ versão 1.0 * @ver Connection * / public final class Identifier {/ ** * Identificador para mensagens internas. * / public static final int INTERNAL = 1; / ** * Identificador para mensagens textuais. * / public static final int TEXT = 2; }

NetworkException.java

/ ** * A classe {@code NetworkException} indica um erro relacionado à rede. * / public class NetworkException extends Exception {/ ** * Constrói uma {@code NetworkException} com {@code null} como sua mensagem. * / public NetworkException () {} / ** * Constrói uma {@code NetworkException} com a mensagem especificada. * * @param message Uma mensagem para descrever o erro. * / public NetworkException (String mensagem) {super (mensagem); } / ** * Constrói uma {@code NetworkException} com a mensagem e a causa especificadas. * * @param message Uma mensagem para descrever o erro. * @param cause A causa do erro. * / public NetworkException (String mensagem, Throwable cause) {super (mensagem, causa); } / ** * Constrói uma {@code NetworkException} com a causa especificada. * * @param cause A causa do erro. * / public NetworkException (Throwable cause) {super (cause); }}

UsageExample.java

/ ** * A classe {@code UsageExample} mostra o uso de {@link Server} e {@link Client}. Este exemplo usa * {@link Thread # sleep (long)} para garantir que cada segmento seja executado, pois o início e o fechamento rápidos fazem com que alguns * segmentos não sejam executados. * * @ versão 1.0 * @see Server * @see Client * / public class UsageExample {public static void main (String args) lança Exceção {String host = "localhost"; porta int = 10430; Servidor servidor = novo servidor (host, porta); Cliente cliente = novo cliente (host, porta); Thread.sleep (100L); client.send ("Olá."); server.broadcast ("Ei, cara!"); Thread.sleep (100L); server.disconnect (server.getConnections () [0]); // ou client.close () para desconectar do lado do cliente server.close (); }}

Recomendado: