Reputation: 81
I'm writing my first java client/server program which just establishes a connection. The client sends it a sentence (file name) and the server sends the file to client.
But when I try to read the name of the file, I get this exception: java.io.UTFDataFormatException: malformed input around byte 65
.
Client:
import java.io.*;
import java.net.*;
public class cliente2 {
public static void main(String[] args) {
Socket yo = null;
PrintWriter alServidor;
BufferedReader delTeclado;
DataInputStream delServidor;
String tecleado;
try {
try {
InetAddress direccion = InetAddress.getByName( "127.0.0.1" );
yo = new Socket(direccion, 400);
} catch (UnknownHostException e) {
System.out.println(e.getMessage());
System.exit(1);
}
System.out.println("El cliente se conecto satisfactoriamente");
delTeclado = new BufferedReader(new InputStreamReader(System.in));
alServidor = new PrintWriter(yo.getOutputStream(), true);
// Creamos flujo de entrada para leer los datos que envia el cliente
delServidor = new DataInputStream(yo.getInputStream());
System.out.print("Por favor digite el archivo que desea descargar ");
tecleado = delTeclado.readLine();
alServidor.println(tecleado);
// System.out.println("Recibiendo el archivo1");
// yo.setSoTimeout( 2000 );
// yo.setKeepAlive( true );
//delTeclado.close();
//alServidor.close();
// Obtenemos el nombre del archivo
String nombreArchivo = dis.readUTF().toString();
System.out.println("Recibiendo el archivoser : " + nombreArchivo);
// Obtenemos el tamano del archivo
int tam = delServidor.readInt();
System.out.println("Recibiendo el archivostam : " + tam);
System.out.println( "Recibiendo archivo2 " + nombreArchivo + tam );
// Creamos flujo de salida, este flujo nos sirve para
// indicar donde guardaremos el archivo
FileOutputStream fos = new FileOutputStream("/home/ubuntu/Documentos/Recibido/" + nombreArchivo);
BufferedOutputStream out = new BufferedOutputStream( fos );
BufferedInputStream in = new BufferedInputStream( yo.getInputStream() );
// Creamos el array de bytes para leer los datos del archivo
byte[] buffer = new byte[tam];
// Obtenemos el archivo mediante la lectura de bytes enviados
for ( int i = 0; i < buffer.length; i++ ) {
buffer[ i ] = ( byte )in.read( );
}
// Escribimos el archivo
out.write( buffer );
// Cerramos flujos
out.flush();
in.close();
out.close();
yo.close();
System.out.println( "Archivo Recibido " + nombreArchivo );
} catch (IOException e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
}
Server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Scanner;
import java.net.*;
import java.io.*;
public class MultiThreadedSocketServer {
ServerSocket myServerSocket;
boolean ServerOn = true;
String Archivo = "" ;
public MultiThreadedSocketServer() {
try {
myServerSocket = new ServerSocket(400);
} catch (IOException ioe) {
System.out.println("Error en la creacion del socket");
System.exit(-1);
}
Calendar now = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println("Hora de Inicio del Servidor : " + formatter.format(now.getTime()));
System.out.println("Esperando Conexiones " + formatter.format(now.getTime()));
System.out.println("*************************** \n");
// Successfully created Server Socket. Now wait for connections.
while (ServerOn) {
try {
// Accept incoming connections.
Socket clientSocket = myServerSocket.accept();
// accept() will block until a client connects to the server.
// If execution reaches this point, then it means that a client
// socket has been accepted.
// For each client, we will start a service thread to
// service the client requests. This is to demonstrate a
// Multi-Threaded server. Starting a thread also lets our
// MultiThreadedSocketServer accept multiple connections simultaneously.
// Start a Service thread
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException ioe) {
System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
try {
myServerSocket.close();
System.out.println("Server Detenido");
} catch (Exception ioe) {
System.out.println("Problema con el Socket , el server se detuvo");
System.exit(-1);
}
}
public static void main (String[] args) {
new MultiThreadedSocketServer();
}
class ClientServiceThread extends Thread {
Socket myClientSocket;
boolean m_bRunThread = true;
public ClientServiceThread() {
super();
}
ClientServiceThread(Socket s) {
myClientSocket = s;
}
public void run() {
// Obtain the input stream and the output stream for the socket
// A good practice is to encapsulate them with a BufferedReader
// and a PrintWriter as shown below.
BufferedReader in = null;
PrintWriter out = null;
// Print out details of this connection
System.out.println("Cliente Conectado IP : " + myClientSocket.getInetAddress() + " Puerto: " + myClientSocket.getLocalPort());
try {
in = new BufferedReader(new InputStreamReader(myClientSocket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(myClientSocket.getOutputStream()));
// At this point, we can read for input and reply with appropriate output.
// Run in a loop until m_bRunThread is set to false
while (m_bRunThread) {
// read incoming stream
String clientCommand = in.readLine();
if (clientCommand.trim() == "Salir") {
System.out.println("Cliente IP : " + myClientSocket.getInetAddress() + " Puerto: " + myClientSocket.getLocalPort());
} else {
System.out.println("Cliente IP : " + myClientSocket.getInetAddress() + " Puerto: " + myClientSocket.getLocalPort());
System.out.println("El cliente solicita el archivo :" + clientCommand);
Archivo = clientCommand;
}
if (!ServerOn) {
// Special command. Quit this thread
System.out.print("El Servidor se encuentra detenido");
out.println("El Servidor se encuentra detenido");
out.flush();
m_bRunThread = false;
}
if (clientCommand.equalsIgnoreCase("Salir")) {
// Special command. Quit this thread
m_bRunThread = false;
System.out.println("Cliente IP : " + myClientSocket.getInetAddress() + " Puerto: " + myClientSocket.getLocalPort());
System.out.print("Salida del Cliente : ");
} else if (clientCommand.equalsIgnoreCase("apagar")) {
// Special command. Quit this thread and Stop the Server
m_bRunThread = false;
System.out.print("El servidor fue desconectado ");
ServerOn = false;
} else {
// Process it
out.println("Enviando el archivo: " + clientCommand);
out.flush();
try {
// Creamos el Socket con la direccion y elpuerto de comunicacion
myClientSocket.setSoTimeout( 2000 );
myClientSocket.setKeepAlive( true );
Archivo = "/home/ubuntu/Documentos/" + clientCommand;
// Creamos el archivo que vamos a enviar
File archivo = new File(Archivo);
// Obtenemos el tamano del archivo
int tamanoArchivo = ( int )archivo.length();
System.out.println( "Tamano del archivo: " + tamanoArchivo );
// Creamos el flujo de salida, este tipo de flujo nos permite
// hacer la escritura de diferentes tipos de datos tales como
// Strings, boolean, caracteres y la familia de enteros, etc.
DataOutputStream dos = new DataOutputStream( myClientSocket.getOutputStream() );
System.out.println( "Enviando Archivo: " + clientCommand );
// Enviamos el nombre del archivo
dos.writeUTF( Archivo );
// Enviamos el tamano del archivo
dos.writeInt( tamanoArchivo );
// Creamos flujo de entrada para realizar la lectura del archivo en bytes
FileInputStream fis = new FileInputStream( archivo );
BufferedInputStream bis = new BufferedInputStream( fis );
// Creamos el flujo de salida para enviar los datos del archivo en bytes
BufferedOutputStream bos = new BufferedOutputStream( myClientSocket.getOutputStream() );
// Creamos un array de tipo byte con el tamano del archivo
byte[] buffer = new byte[tamanoArchivo];
// Leemos el archivo y lo introducimos en el array de bytes
bis.read( buffer );
// Realizamos el envio de los bytes que conforman el archivo
for ( int i = 0; i < buffer.length; i++ ) {
bos.write( buffer[ i ] );
}
System.out.println( "Archivo Enviado: " + archivo.getName() );
// Cerramos socket y flujos
bis.close();
bos.close();
} catch ( Exception e ) {
System.out.println(e.toString());
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Clean up
try {
in.close();
out.close();
myClientSocket.close();
System.out.println("Cliente Desconectado");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
}
Upvotes: 1
Views: 6372
Reputation: 310916
The problem here is that you are using both a BufferedReader
and a DataInputStream
on the same socket. BufferedReader
fills its buffer and steals at least part of the following data, which includes the archive name, the length, and the data. So when readUTF()
executes, the next thing in the stream isn't the archive name written by writeUTF().
You should probably just use writeUTF()
and readUTF()
throughout, and get rid of the BufferedReader
and PrintWriter
altogether.
Upvotes: 2