Java – Transferindo arquivos via socket

Bom dia,
Faz tempo que não coloco um código no site, fiz algo simples porem útil no dia a dia.
Como transferir arquivos via socket utilizando o Java, caso tenha alguma melhor maneira ou dúvida, favor entre em contato.

Coloquei a explicação nos comentários em cada parte das classes. Para testar basta executar a classe Server e depois a Cliente, alterando somente o arquivo que deseja transferir.

Seguem as classes:
– ServerTransfer.java
– ClientTransfer.java

Veja a seguir o coteúdo:

Console do Servidor

Porta de conexao aberta 13267
Conexao recebida pelo cliente
Lendo arquivo...
Enviando Arquivo...
Arquivo Enviado!

Console do Cliente

Conectando com Servidor porta 13267
Arquivo Local Criado c:\temp\source-copy.zip
Recebendo arquivo...
Arquivo recebido!

Classe para o Servidor ServerTransfer.java

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**@author Lucas iorio - http://www.byiorio.com
 * 
 * @author Lucas iorio - http://www.byiorio.com
 *
 */
public class ServerTransfer {
	public static void main(String[] args) {

		// Criando servidor
		ServerTransfer server = new ServerTransfer();

		// Aguardar conexao de cliente para transferia
		server.waitForClient();
		
	}

	public void waitForClient() {
		// Checa se a transferencia foi completada com sucesso
		OutputStream socketOut = null;
		ServerSocket servsock = null;
		FileInputStream fileIn = null;

		try {
			// Abrindo porta para conexao de clients
			servsock = new ServerSocket(13267);
			System.out.println("Porta de conexao aberta 13267");

			// Cliente conectado
			Socket sock = servsock.accept();
			System.out.println("Conexao recebida pelo cliente");

			// Criando tamanho de leitura
			byte[] cbuffer = new byte[1024];
			int bytesRead;

			// Criando arquivo que sera transferido pelo servidor
			File file = new File("c:\\temp\\teste.zip");
			fileIn = new FileInputStream(file);
			System.out.println("Lendo arquivo...");
			
			// Criando canal de transferencia
			socketOut = sock.getOutputStream();

			// Lendo arquivo criado e enviado para o canal de transferencia
			System.out.println("Enviando Arquivo...");
			while ((bytesRead = fileIn.read(cbuffer)) != -1) {
				socketOut.write(cbuffer, 0, bytesRead);
				socketOut.flush();
			}

			System.out.println("Arquivo Enviado!");
		} catch (Exception e) {
			// Mostra erro no console
			e.printStackTrace();
		} finally {
			if (socketOut != null) {
				try {
					socketOut.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (servsock != null) {
				try {
					servsock.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (fileIn != null) {
				try {
					fileIn.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

/**@author Lucas iorio – http://www.byiorio.com
*
* @author Lucas iorio – http://www.byiorio.com
*
*/
Classe java cliente ClientTransfer.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ClientTransfer {
	public static void main(String[] args) {

		//Criando Classe cliente para receber arquivo
		ClientTransfer cliente = new ClientTransfer();

		//Solicitando arquivo
		cliente.getFileFromServeR();
	}

	private void getFileFromServeR() {
		Socket sockServer = null;
		FileOutputStream fos = null;
		InputStream is = null;

		try {
			// Criando conexão com o servidor
			System.out.println("Conectando com Servidor porta 13267");
			sockServer = new Socket("127.0.0.1", 13267);
			is = sockServer.getInputStream();

			// Cria arquivo local no cliente
			fos = new FileOutputStream(new File("c:\\temp\\source-copy.zip"));
			System.out.println("Arquivo Local Criado c:\\temp\\source-copy.zip");
			
			// Prepara variaveis para transferencia
			byte[] cbuffer = new byte[1024];
			int bytesRead;

			// Copia conteudo do canal
			System.out.println("Recebendo arquivo...");
			while ((bytesRead = is.read(cbuffer)) != -1) {
				fos.write(cbuffer, 0, bytesRead);
				fos.flush();
			}
			
			System.out.println("Arquivo recebido!");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (sockServer != null) {
				try {
					sockServer.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}

			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}

			if (is != null) {
				try {
					is.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}

	}
}

8 comentários em “Java – Transferindo arquivos via socket

  • 7 de janeiro de 2015 em 13:35
    Permalink

    Olá, não consegui enviar o arquivo.
    Estou mudando o arquivo para uma imagem .jpg.
    O local no qual a imagem está no servidor é diferente de onde o cliente irá receber.
    Este é o meu console ao executar o servidor e o cliente, respectivamente.

    Porta de conexao aberta 13267
    Conexao recebida pelo cliente
    Lendo arquivo…
    Enviando Arquivo…
    java.net.SocketException: Software caused connection abort: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(Unknown Source)
    at java.net.SocketOutputStream.write(Unknown Source)
    at ftp_server.Servidor.waitForClient(Servidor.java:51)
    at ftp_server.Servidor.main(Servidor.java:18)

    Resposta
  • 7 de janeiro de 2015 em 15:27
    Permalink

    Caio,
    Alterei meu exemplo aqui para JPG e transferi um arquivo JPG de 789k sem problemas.

    Algumas perguntas
    1) Em seu teste o servidor e o client estão na mesma máquina?
    2) Você fez um teste utilizando exatamente as classes acima?

    Resposta
  • 7 de janeiro de 2015 em 16:00
    Permalink

    Esse problema pode ser várias coisas

    1) Reutilização de socket de maneira errada
    S:Verificar se está fechando e abrindo o socket corretamente

    2) Timeout
    S:No caso de timeout você pode colocar um valor

    DE

    sockServer = new Socket("127.0.0.1", 13267);
    

    PARA

    sockServer = new Socket();
    SocketAddress sockaddr = new InetSocketAddress("127.0.0.1", 13267);
    sockServer.connect(sockaddr, 180000);
    
    Resposta
  • 8 de abril de 2015 em 20:57
    Permalink

    Boa noite Lucas, consegui rodar o seu código com sucesso! mas eu não entendi como funciona o WHILE no lado do Servidor, voce poderia me explicar a lógica dele, fazendo favor?

    “while ((bytesRead = fileIn.read(cbuffer)) != -1)”

    Quando que ele chega a esse valor de -1?

    Ele pega o tamanho do arquivo e a cada envio “descrementa” o tamanho dele até chegar a 0 byte? é algo assim?

    Essa variavel “bytesRead” é o tamanho do arquivo? e o CBUFFER um array de byte?

    Muito obrigado.

    Resposta
  • 13 de abril de 2015 em 21:26
    Permalink

    Tudo bom Daniel? Obrigado por ter enviado a pergunta… Uma boa pergunta e difícil de responder via texto… mas vamos lá tentarei explicar da melhor maneira possível

    1) Quando usamos o WHILE, temos que colocar uma condição de TRUE ou FALSE para ele continuar ou não o loop, certo? Neste caso a condição verifica isso…

    2) Quando executamos o comando

    bytesRead = fileIn.read(cbuffer)

    significa que estamos lendo o conteúdo que está na variável “fileIn” e jogando na variável “cbuffer”.

    3) O cbuffer tem um tamanho de 1024, ou seja, ele só pode ler 1024 bytes mas o arquivo pode ter mais que isso certo? Então ele vai preencher os 1024 do cbuffer e retornar para variável bytesRead que foi lido 1024, preenchendo todo o array.

    4) Ele repetirá o processo e quando não tiver mais nada para ele, ele retornará -1 mudando a condição do loop para FALSE, forçando a saída

    RESUMO: se tivermos um arquivo e 9.5mb, teremos 9 loops que o bytesRead receberá o resultado 1024, no 10 loop ele receberá 500 e no 11 loop ele receberá -1, dizendo que não tem mais nada para ler

    Resposta
  • 17 de abril de 2015 em 15:42
    Permalink

    Tudo sim, obrigado por tentar me explicar, deu uma bela esclarecida!

    Acho que agora entendi!

    Nesse exemplo q vc deu no resumo, na verdade é um arquivo de 9.5Kb nao é? por causa que o tamanho da variavel é de 1024 bytes (1KB). E em cada loop transfere 1KB do arquivo.

    Entao, a “bytesRead” no 10° loop vai receber os ultimos 500 bytes do arquivo, e no 11° loop como tá vazia ela recebe -1.

    Resposta
  • 15 de outubro de 2015 em 08:14
    Permalink

    Olá, parabéns pelo excelente conteúdo diponibilizado. Minha dúvida é se tem como colocar uma opção do destinatário recusar o recebimento do arquivo vinda do remetente. Caso tenha como sera?

    Desde já agradeço

    Resposta
  • 15 de abril de 2016 em 11:36
    Permalink

    Uma pergunta:
    Para rodar em cliente servidor, a classe
    ServerTransfer
    deve estar no servidor?
    e o ClientTransfer no cliente?

    Eu gostaria de transferir uma lista de arquivos do servidor local para a estação do cliente, deste metodo é possivel?

    Resposta

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Blue Captcha Image
Atualizar

*

Facebook

Get the Facebook Likebox Slider Pro for WordPress
WordPress SEO fine-tune by Meta SEO Pack from Poradnik Webmastera