Introdução
Uma dúvida de um aluno da Academia Java me incentivou a dar continuidade ao assunto de programação Java para redes, iniciado em Java e Redes: Consultando um serviço com Socket que mostrava como consultar um serviço do NIST por meio da API de redes da Plataforma Java, este post apresenta a implementação de um
Exemplo
Para a criação de um
Apenas a criação do objeto
ServerFileSocket.java
Segue o código completo da classe que implementa o servidor que responde aos clientes com o arquivo determinado.
Esta classe não está explicada detalhadamente no artigo, porém acredito que o artigo anterior: Java e Redes: Consultando um serviço com Socket, juntamente com este podem esclarecer sobre o funcionamento da classe.
Outro ponto importante, é com relação a porta utilizada, caso a porta 8080 já esteja sendo utilizada, basta alterar a variável
Além disso é possível alterar o arquivo enviado, alterando o valor da variável
Teste se possível em máquinas diferentes, alterando as variáveis indicadas, tente ainda alterar o arquivo enviado.
Até mais!
Marcelo de Castro
Uma dúvida de um aluno da Academia Java me incentivou a dar continuidade ao assunto de programação Java para redes, iniciado em Java e Redes: Consultando um serviço com Socket que mostrava como consultar um serviço do NIST por meio da API de redes da Plataforma Java, este post apresenta a implementação de um
java.net.ServerSocket
que responde aos clientes com um determinado arquivo.Exemplo
Para a criação de um
ServerSocket
que será responsável por escrever os bytes de um determinado arquivo no canal de comunicação com o cliente, definiremos a porta no construtor, conforme segue:int port = 8080; ServerSocket server = new ServerSocket(8080);
Apenas a criação do objeto
server
da classe ServerSocket
não permite ainda a comunicação, para tanto é necessário que o ServerSocket
passe a aceitar conexões, e isto é feito pelo método accept
, este método é bloqueante, ou seja, faz com que o programa fique parado até que o servidor receba uma requisição, e quando isto ocorrer cria um Socket
para comunicação; Socket
este que tem sua referência armazenada na variável socket
, de acordo com a linha apresentada abaixo:Socket socket = server.accept();E então, após uma requisição ser recebida, podemos recuperar o fluxo para escrita no socket, por meio do método
getOutputStream
e montar o fluxo de escrita otimizado com uso de um objeto do tipo BufferedOutputStream
, conforme trecho de código abaixo:OutputStream socketOutput = socket.getOutputStream(); BufferedOutputStream output = new BufferedOutputStream(socketOutput);Para ler o arquivo determinado criaremos um fluxo de leitura otimizado, conforme segue:
String pathname = "feed.png"; FileInputStream fileInput = new FileInputStream(pathname); BufferedInputStream input = new BufferedInputStream(fileInput);Depois de montado o fluxo de entrada (
input
), que lê um determinado arquivo, e o fluxo de saída (output
), basta realizar a leitura da entrada e escrever na saída, enquanto existirem bytes a serem lidos, conforme trecho abaixo:int data = 0; while( (data = input.read()) !=-1){ output.write(data); }O método accept está em um laço infinito
while(true){}
e a forma de interromper a execução do servidor é interromper o processo no console ou na sua IDE preferida, ou ainda determinar a quantidade de vezes que o servidor vai executar o laço.ServerFileSocket.java
Segue o código completo da classe que implementa o servidor que responde aos clientes com o arquivo determinado.
package br.eti.castro.blog.samples.networking; // imports ocultos public class ServerFileSocket { //o tratamento de excessoes foi simplificado (throws UnknownHostException, IOException) //para simplificar o entendimento do exemplo public static void main(String[] args) throws IOException { //declarando de objetos para a leitura do arquivo String pathname = "feed.png";//pode conter o caminho BufferedInputStream input = null; FileInputStream fileInput = null; //declarando de objetos para a escrita no fluxo do socket OutputStream socketOutput = null; BufferedOutputStream output = null; //Criando um servidor que atendera na porta 8080 int port = 8080; ServerSocket server = new ServerSocket(port); while(true){ //O metodo accept faz com que o servidor aguarde uma requisicao //Quando isto ocorrer cria um Socket para comunicacao Socket socket = server.accept(); //montando o fluxo de leitura do arquivo otimizado fileInput = new FileInputStream(pathname); input = new BufferedInputStream(fileInput); //montando o fluxo de dados para escrita no socket socketOutput = socket.getOutputStream(); output = new BufferedOutputStream(socketOutput); int data = 0; //lendo o arquivo while( (data = input.read()) !=-1){ //escrevendo o dado lido no socket output.write(data); } //fechando o fluxo de entrada input.close(); //fechando o fluxo de saida output.flush(); output.close(); //fechando o socket socket.close(); } } }ClientFileSocket.java
Esta classe não está explicada detalhadamente no artigo, porém acredito que o artigo anterior: Java e Redes: Consultando um serviço com Socket, juntamente com este podem esclarecer sobre o funcionamento da classe.
package br.eti.castro.blog.samples.networking; //imports ocultos public class ClientFileSocket { //o tratamento de excessoes foi simplificado (throws UnknownHostException, IOException) //para simplificar o entendimento do exemplo public static void main(String[] args) throws UnknownHostException, IOException { //declarando de objetos para a leitura do fluxo do socket BufferedInputStream input = null; InputStream socketInput = null; //declarando de objetos para a escrita do arquivo String pathname = "novo.png"; FileOutputStream fileOutput = null; BufferedOutputStream output = null; //criando o socket para o localhost na porta 8080 String host = "localhost"; int port = 8080; Socket socket = new Socket(host, port); //recuperando o fluxo de dados socketInput = socket.getInputStream(); //montando o fluxo de leitura do socket otimizado input = new BufferedInputStream(socketInput); //montando o fluxo de escrita do arquivo otimizado fileOutput = new FileOutputStream(pathname); output = new BufferedOutputStream(fileOutput); //lendo o socket int i = 0; while( (i = input.read()) !=-1){ //escrevendo o arquivo output.write(i); } //fechando o fluxo de entrada input.close(); //fechando o fluxo de saida output.flush(); output.close(); //fechando o socket socket.close(); } }O exemplo está preparado para rodar ambas as classes na mesma máquina, pois a classe
ClientFileSocket
está configurada para procurar o ServerSocket
na mesma máquina (host = "localhost"
), porém é interessante rodar cada uma das classes em uma máquina diferente, bastando para tanto alterar o valor da variável host.Outro ponto importante, é com relação a porta utilizada, caso a porta 8080 já esteja sendo utilizada, basta alterar a variável
port
, que deve ter sempre o mesmo valor na classe ServerFileSocket
e na classe ClientFileSocket
.Além disso é possível alterar o arquivo enviado, alterando o valor da variável
pathname
na classe ServerFileSocket
e também o nome em que a classe ClientFileSocket
salva o arquivo alterando variável de mesmo nome.Teste se possível em máquinas diferentes, alterando as variáveis indicadas, tente ainda alterar o arquivo enviado.
Até mais!
Marcelo de Castro
http://twitter.com/mcastroinfo
http://www.globalcode.com.br/instrutores/MarceloCastro
Outros posts: http://blog.globalcode.com.br/search/label/MarceloCastro
Comentários