2012-09-03 14 views
5

Estoy escribiendo una aplicación que necesita enviar un archivo a través de la red. Solo me han enseñado a usar las clases estándar java.net y java.io hasta ahora (en mi primer año de universidad), así que no tengo experiencia con java.nio y netty y todas esas cosas lindas. Tengo un servidor/cliente de trabajo creado usando clases Socket y ServerSocket junto con BufferedInput/OutputStreams y BufferedFile arroyos, de la siguiente manera:¿Cómo puedo almacenar correctamente mi flujo de entrada/salida/archivo Java?

El servidor:

public class FiletestServer { 

    static ServerSocket server; 
    static BufferedInputStream in; 
    static BufferedOutputStream out; 

    public static void main(String[] args) throws Exception { 
    server = new ServerSocket(12354); 
    System.out.println("Waiting for client..."); 
    Socket s = server.accept(); 
    in = new BufferedInputStream(s.getInputStream(), 8192); 
    out = new BufferedOutputStream(s.getOutputStream(), 8192); 
    File f = new File("test.avi"); 
    BufferedInputStream fin = new BufferedInputStream(new FileInputStream(f), 8192); 

    System.out.println("Sending to client..."); 
    byte[] b = new byte[8192]; 
    while (fin.read(b) != -1) { 
     out.write(b); 
    } 
    fin.close(); 
    out.close(); 
    in.close(); 
    s.close(); 
    server.close(); 
    System.out.println("done!"); 
    } 
} 

y el cliente:

public class FiletestClient { 

    public static void main(String[] args) throws Exception { 
    System.out.println("Connecting to server..."); 
    Socket s; 
    if (args.length < 1) { 
     s = new Socket("", 12354); 
    } else { 
     s = new Socket(args[0], 12354); 
    } 
    System.out.println("Connected."); 
    BufferedInputStream in = new BufferedInputStream(s.getInputStream(), 8192); 
    BufferedOutputStream out = new BufferedOutputStream(s.getOutputStream(), 8192); 
    File f = new File("test.avi"); 
    System.out.println("Receiving..."); 
    FileOutputStream fout = new FileOutputStream(f); 
    byte[] b = new byte[8192]; 
    while (in.read(b) != -1) { 
     fout.write(b); 
    } 
    fout.close(); 
    in.close(); 
    out.close(); 
    s.close(); 
    System.out.println("Done!"); 
    } 
} 

Al principio no estaba usando el búfer y escribía cada int desde in.read(). Eso me dio una transferencia de 200kb/s según mi gadget de monitor de red en Windows 7. Luego lo cambié como arriba pero usé buffers de 4096 byte y obtuve la misma velocidad, pero el archivo recibido usualmente era un par de kilobytes más grande que el archivo fuente, y ese es mi problema. Cambié el tamaño del búfer a 8192 y ahora obtengo una transferencia de 3.7-4.5mb/seg a través de la conexión inalámbrica a mi computadora portátil, que es lo suficientemente rápido por ahora, pero todavía tengo el problema de que el archivo se haga un poco más grande (lo que causaría fallar una prueba de hash md5/sha) cuando se recibe.

Así que mi pregunta es ¿cuál es la forma correcta de almacenamiento en búfer para obtener velocidades decentes y terminar exactamente con el mismo archivo en el otro lado? Hacer que vaya un poco más rápido también sería bueno, pero estoy contento con la velocidad por ahora. Supongo que un buffer más grande es mejor hasta cierto punto, solo necesito encontrar cuál es ese punto.

Respuesta

5

Está ignorando el tamaño de los datos realmente leídos.

while (in.read(b) != -1) { 
    fout.write(b); 
} 

siempre escribirá 8192 bytes aunque se lea solo un byte. En su lugar se sugiere emplear

for(int len; ((len = in.read(b)) > 0;) 
    fout.write(b, 0, len); 

Sus memorias intermedias son del mismo tamaño que el byte [] por lo que no están realmente haciendo nada por el momento.

La MTU para la mayoría de las redes es de alrededor de 1500 bytes y se obtiene una mejora del rendimiento en redes más lentas (hasta 1 GB) de hasta 2 KB. 8 KB tan bien también. Más grande que eso es poco probable que ayude.

+0

Ah, sígueme. – martijno

+0

@martijno Una señal que necesito reducir la velocidad. ;) –

+0

Entiendo que ignorar la parte de tamaño de datos que causa el problema, pero no entiendo eso para el ciclo. De alguna manera, parece que lee adelante de una manera y solo escribe datos desde el búfer hasta el punto donde finaliza el contenido real, ¿es correcto? EDITAR: tiene demasiados corchetes, "((len = ..." debería ser "(len = ..." – Logan

Cuestiones relacionadas