Las clases , a continuación, son la base de la aplicación, ya que en su totalidad está desarrollada con Swing. Primero que todo cree una clase base en la que tengo los recursos bases, que tanto como el cliente y el servidor utilizan. Ambas implementan la clase Runnable, ya que necesitamos de hilos para que nuestra aplicación funcione.
Para los que desean el código fuente lo pueden obtener aquí.
/**
* Clase base para el cliente y el servidor.
* @author usuario
*
*/
public abstract class FileTransportBase implements Runnable{
/**
* Flujo de salida
*/
protected ObjectOutputStream oos;
/**
* Flujo de entrada
*/
protected ObjectInputStream ois;
/**
* Objeto que viaja entre el cliente y el servidor
*/
protected FileTransport ft;
protected int port;
protected Socket socket;
/**
* Ruta del archivo en el cliente, rutal de la carpeta en el servidor
*/
protected String path;
protected JTextArea jTextArea;
protected JScrollPane jScrollPane;
public ObjectOutputStream getOos() {
return oos;
}
public void setOos(ObjectOutputStream oos) {
this.oos = oos;
}
public ObjectInputStream getOis() {
return ois;
}
public void setOis(ObjectInputStream ois) {
this.ois = ois;
}
public FileTransport getFt() {
return ft;
}
public void setFt(FileTransport ft) {
this.ft = ft;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public JTextArea getjTextArea() {
return jTextArea;
}
public void setjTextArea(JTextArea jTextArea) {
this.jTextArea = jTextArea;
}
public JScrollPane getjScrollPane() {
return jScrollPane;
}
public void setjScrollPane(JScrollPane jScrollPane) {
this.jScrollPane = jScrollPane;
}
/**
* Agrega mensajes a la consola de la aplicación
* @param msg
*/
public void addMessage(String msg) {
Util.addMessage(jTextArea, jScrollPane, msg);
}
}
Cliente
El cliente hereda de la clase FileTransportBase.
/**
* Clase cliente
* @author usuario
*
*/
public class Client extends FileTransportBase {
/**
* Direccion Ip a la que se conectara el cliente
*/
private InetAddress host;
/**
* Archivo que se va enviar
*/
private File file;
/**
* Constructor para pruebas locales
*
* @param pathFile
*/
public Client(String pathFile) {
try {
this.host = InetAddress.getLocalHost();
this.port = Util.PORT;
this.path = pathFile;
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* @param ipAddress Ip del Servidor
* @param port Puerto del Servidor
*/
public Client(String ipAddress, int port) {
try {
this.host = InetAddress.getByName(ipAddress);
this.port = port;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
System.out.println("El host no existe");
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (this) {
Thread.currentThread();
}
try {
init();
sendFile();
} catch (FileTransportException e) {
// TODO Auto-generated catch block
addMessage(e.getMessage());
}
}
/**
* Inicia la conexion con el servidor
* @throws FileTransportException
*/
private void init() throws FileTransportException {
try {
addMessage("Conectando con el Servidor...");
this.socket = new Socket(this.host, this.port);
} catch (IOException e) {
throw new FileTransportException("Ha ocurrido un error: "
+ e.getMessage());
}
}
/**
* Envia un objeto de tipo {@link FileTransport}
*
* @throws FileTransportException
*/
private void sendFile() throws FileTransportException {
String name;
byte[] byteFile;
if (this.path != null)
file = new File(this.path);
try {
this.oos = new ObjectOutputStream(socket.getOutputStream());
name = file.getName();
byteFile = Util.getBytesFromFile(file);
this.ft = new FileTransport();
this.ft.setName(name);
this.ft.setFilearray(byteFile);
this.oos.writeObject(this.ft);
addMessage("El archivo " + name + " fue enviado al servidor");
this.ois = new ObjectInputStream(socket.getInputStream());
addMessage("Respuesta Servidor: " + (String) ois.readObject());
this.socket.close();
} catch (IOException e) {
throw new FileTransportException("Ha ocurrido un error: "
+ e.getMessage());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
}
Server
El server hereda de la clase FileTransportBase.
/**
* Clase server
* @author usuario
*
*/
public class Server extends FileTransportBase {
private ServerSocket serverSocket;
private boolean isStopped = false;
public Server() {
}
/**
*
* @param port Puerto en el que arrancar el servidor
* @param path Ruta donde se guardaran los archivos
*/
public Server(int port, String path) {
this.port = port;
this.path = path;
}
@Override
public void run() {
synchronized (this) {
Thread.currentThread();
}
addMessage("Iniciando...");
try {
this.serverSocket = new ServerSocket(this.port);
} catch (IOException e) {
e.printStackTrace();
addMessage("Error al abrir el puerto " + this.port);
}
addMessage("Servidor abierto en el puerto "
+ this.serverSocket.getLocalPort());
while (!isStopped()) {
openConnection();
}
}
private synchronized boolean isStopped() {
return this.isStopped;
}
public synchronized void stop() {
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void start() {
this.isStopped = false;
}
/**
* Este método aguarda a que hallá un conexión por parte del cliente
* lee la entrada y escribe el archivo en disco y envia una respuesta al cliente
*/
private void openConnection() {
try {
addMessage("Esperando Conexion...");
this.socket = this.serverSocket.accept();
addMessage("Conexion desde " + this.socket.getInetAddress());
this.ois = new ObjectInputStream(this.socket.getInputStream());
ft = (FileTransport) ois.readObject();
Util.writeBytesToFile(ft.getFilearray(), this.path + ft.getName());
addMessage("Copiado en " + this.path + ft.getName());
this.oos = new ObjectOutputStream(this.socket.getOutputStream());
addMessage("Enviando Respuesta al cliente...");
this.oos.writeObject("El archivo fue recibido exitosamente");
this.ois.close();
this.socket.close();
} catch (SocketException e) {
if (isStopped()) {
addMessage("El servidor esta parado");
}
} catch (IOException e) {
// TODO Auto-generated catch block
addMessage(e.getMessage());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (this.ois != null)
this.ois.close();
if (this.socket != null)
this.socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Clase Util
En esta clase tenemos una serie de funciones que son usadas tanto el cliente como en el servidor.
/**
* Clase que contiene utilidades
*
* @author usuario
*
*/
public class Util {
/**
* Puerto por defecto
*/
public static final int PORT = 2011;
/**
* Convierte un objeto de tipo {@link File} a un arreglo de bytes
*
* @param file
* Archivo a Convertir
* @return byte[]
* @throws IOException
* @throws FileTransportException
*/
public static byte[] getBytesFromFile(File file) throws IOException,
FileTransportException {
InputStream is;
int length;
byte[] bytes;
int offset = 0;
int numRead = 0;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
throw new FileTransportException("No se encuentra el archivo");
}
length = (int) file.length();
if (length > Integer.MAX_VALUE) {
throw new FileTransportException("El archivo es demasiado grande");
}
bytes = new byte[length];
while (offset < bytes.length
&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new FileTransportException("El archivo " + file.getName()
+ " no fue convertido.");
}
is.close();
return bytes;
}
/**
* Convierte un arreglo de bytes en un objeto de tipo {@link File} y lo
* escribe en disco
*
* @param byteArray
* arreglo a escribir
* @param pathFile
* ruta donde se escribe el archivo
* @throws IOException
*/
public static void writeBytesToFile(byte[] byteArray, String pathFile)
throws IOException {
ByteArrayInputStream bis;
File file;
OutputStream out;
byte[] buf;
int len;
file = new File(pathFile);
if (!file.exists()) {
file.createNewFile();
}
bis = new ByteArrayInputStream(byteArray);
out = new FileOutputStream(file);
buf = new byte[1024];
while ((len = bis.read(buf)) > 0)
out.write(buf, 0, len);
out.close();
bis.close();
}
/**
* Agrega un mensaje a la consola Java y a la consola de la aplicacion
* @param console JtextArea, enviar null si se va usar System.out.
* @param consoleScroll JScrollPane null si se va usar System.out.
* @param msg Mensaje
*/
public static void addMessage(final JTextArea console,
final JScrollPane consoleScroll, final String msg) {
if (console != null && consoleScroll != null) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
console.append(msg + "\n");
Dimension consoleSize = console.getSize();
Point point = new Point(0, consoleSize.height);
consoleScroll.getViewport().setViewPosition(point);
}
});
}
System.out.println(msg);
}
}
y por ùltimo el objeto que viaja.
/**
* Objeto que viaja atraves del Socket
* @author usuario
*
*/
public class FileTransport extends Object implements Serializable {
private static final long serialVersionUID = 8458553842346689548L;
private String name;
private byte[] filearray;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getFilearray() {
return filearray;
}
public void setFilearray(byte[] filearray) {
this.filearray = filearray;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "[" + this.name +"]";
}
}