2015-03-25 1 views
0

У меня проблема с filetransfer с использованием SocketChannels: клиент заканчивает передачу файла, но сервер все еще ждет больше байта от клиента. Это приведет к таймауту, и файл будет сохранен меньше, чем небольшая часть. Сервер остается застрявшим здесь: «fileChannel.transferFrom (socketChannel, 0, fileLength);». Все, что происходит раньше, работает правильно.java Filetransfer с SocketChannel

сервер:

import java.io.BufferedReader; 
import java.io.ByteArrayInputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.RandomAccessFile; 
import java.nio.channels.FileChannel; 
import java.nio.channels.SocketChannel; 

import javax.imageio.ImageIO; 

public class RequestHandler implements Runnable { 

private SocketChannel socketChannel; 

BufferedReader stringIn; 

public RequestHandler(SocketChannel socketChannel) { 
    this.socketChannel = socketChannel; 
    // this.serverSocketChannel = socketChannel; 
    System.out.println("RequestHandler initialized"); 
} 

public static int getLastPush(String dir) { 
    return new File("./" + dir).listFiles().length + 1; 
} 

public void run() { 

    LoadConfig config = null; 
    try { 
     config = new LoadConfig(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    String type = null; 

    try { 

     socketChannel.socket().setSoTimeout(10000); 
     MainServer.log("Client connected from: " + socketChannel); 

     // Prendere immagine 
     DataInputStream dis = new DataInputStream(socketChannel.socket().getInputStream()); 

     // Leggo string 
     stringIn = new BufferedReader(new InputStreamReader(socketChannel.socket().getInputStream())); 

     // Invio al client 
     DataOutputStream dos = new DataOutputStream(socketChannel.socket().getOutputStream()); 

     // leggo in ricezione 
     MainServer.log("Attendo auth"); 
     String auth = stringIn.readLine(); 

     // check auth 
     MainServer.log("Auth ricevuto: " + auth); 

     String pass = config.getPass(); 
     if (pass.equals(auth)) { 
      dos.writeBytes("OK\n"); 
      System.out.println("Client Authenticated"); 

      type = stringIn.readLine(); 
      System.out.println("fileType: " + type); 

      dos.writeBytes(type + "\n"); 

      Integer i = getLastPush(config.getFolder()); 

      String fileName = i.toString(); 
      System.out.println("fileName: " + fileName); 

      switch (type) { 

      case "img": 

       // transfer image 
       int len = dis.readInt(); 
       System.out.println("Transfer started."); 
       byte[] data = new byte[len]; 
       dis.readFully(data); 
       System.out.println("Transfer ended."); 

       File toWrite = new File(config.getFolder() + "/" + fileName + ".png"); 

       ImageIO.write(ImageIO.read(new ByteArrayInputStream(data)), "png", toWrite); 

       dos.writeBytes("http://" + config.getDomain() + "/" + toWrite.getName()); 

       break; 
      case "file": 

       // transfer file 
       System.out.println("Transfer started."); 

       readFileFromSocket(config.getFolder() + "/" + fileName + ".zip"); 
       System.out.println("Transfer ended."); 

       System.out.println("Sending link..."); 
       dos.writeBytes("http://" + config.getDomain() + "/" + fileName + ".zip"); 

       break; 
      default: 

      } 

      i++; 

      System.out.println("Chiudo"); 
      dos.close(); 
      dis.close(); 
      stringIn.close(); 
     } else { 
      dos.writeBytes("Invalid Id or Password"); 
      System.out.println("Invalid Id or Password"); 
      dos.close(); 
      dis.close(); 
      stringIn.close(); 
     } 

     socketChannel.close(); 

    } catch (Exception exc) { 
     exc.printStackTrace(); 
    } 
    System.out.println("----------"); 
} 

public void readFileFromSocket(String fileName) { 
    RandomAccessFile aFile = null; 
    try { 
     aFile = new RandomAccessFile(fileName, "rw"); 
     FileChannel fileChannel = aFile.getChannel(); 

     long fileLength = Long.parseLong(stringIn.readLine()); 
     System.out.println("File length: " + fileLength); 

     fileChannel.transferFrom(socketChannel, 0, fileLength); 
     fileChannel.close(); 

     Thread.sleep(1000); 
     fileChannel.close(); 
     System.out.println("End of file reached, closing channel"); 

    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

} 

} 

клиента:

import java.awt.AWTException; 
import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.image.BufferedImage; 
import java.io.BufferedReader; 
import java.io.ByteArrayOutputStream; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.RandomAccessFile; 
import java.net.InetSocketAddress; 
import java.net.SocketAddress; 
import java.net.UnknownHostException; 
import java.nio.channels.FileChannel; 
import java.nio.channels.SocketChannel; 

import javax.imageio.ImageIO; 

public class Uploader { 
    private BufferedImage img; 
    private byte[] bytes; 
    private SocketChannel socketChannel; 
    private String link; 
    private String fileName; 

    DataOutputStream dos; 

    // Per gli screen parziali 
    public Uploader(Rectangle r, String ip, int port) throws IOException, AWTException { 

     SocketChannel socketChannel = createChannel(ip, port); 
     this.socketChannel = socketChannel; 

     Rectangle screenRect = new Rectangle(0, 0, 0, 0); 
     for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { 
      screenRect = screenRect.union(gd.getDefaultConfiguration().getBounds()); 
     } 

     this.img = new Robot().createScreenCapture(screenRect).getSubimage(r.x, r.y, r.width, r.height); 

     ByteArrayOutputStream outputArray = new ByteArrayOutputStream(); 
     ImageIO.write(img, "png", outputArray); 
     outputArray.flush(); 
     this.bytes = outputArray.toByteArray(); 
     outputArray.close(); 
    } 

    // Per gli screen completi 
    public Uploader(BufferedImage bi, String ip, int port) throws IOException { 

     SocketChannel socketChannel = createChannel(ip, port); 
     this.socketChannel = socketChannel; 
     this.img = bi; 

     ByteArrayOutputStream outputArray = new ByteArrayOutputStream(); 
     ImageIO.write(img, "png", outputArray); 
     outputArray.flush(); 
     this.bytes = outputArray.toByteArray(); 
     outputArray.close(); 
    } 

    // Per i file 
    public Uploader(String fileName, String ip, int port) throws UnknownHostException, IOException { 

     SocketChannel socketChannel = createChannel(ip, port); 
     this.socketChannel = socketChannel; 

     // this.socket = new Socket(ip, port); 
     this.fileName = fileName; 
    } 

    public void send(String pass, String type) throws IOException { 

     dos = new DataOutputStream(socketChannel.socket().getOutputStream()); 
     BufferedReader stringIn = new BufferedReader(new InputStreamReader(socketChannel.socket().getInputStream())); 

     try { 
      socketChannel.socket().setSoTimeout(10000); 

      // send auth 
      System.out.println("Sending auth"); 
      dos.writeBytes(pass + "\n"); 
      System.out.println("Auth sent: " + pass); 
      this.link = stringIn.readLine(); 
      // this.link = os.println(); 
      System.out.println("Auth reply: " + link); 
      if (this.link.equals("OK")) { 

       System.out.println("Sending type: " + type); 
       dos.writeBytes(type + "\n"); 

       // Controllo e aspetto che il server abbia ricevuto il type 
       // corretto 
       if (stringIn.readLine().equals(type)) { 

        System.out.println("Il server riceve un: " + type); 

        switch (type) { 

        // image transfer 
        case "img": 

         System.out.println("Uploading image..."); 

         dos.writeInt(bytes.length); 
         dos.write(bytes, 0, bytes.length); 
         dos.flush(); 

         break; 

        // file transfer 
        case "file": 

         sendFile(fileName); 

         break; 

        // default case, hmm 
        default: 

         break; 
        } 

        // return link 
        System.out.println("Waiting link..."); 
        this.link = stringIn.readLine(); 
        System.out.println("Returned link: " + link); 

        bytes = null; 
       } else { 
        System.out.println("The server had a bad interpretation of the fileType"); 
       } 

      } else { 
       System.out.println("Closed"); 
      } 

      dos.close(); 
      stringIn.close(); 
      socketChannel.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public SocketChannel createChannel(String ip, int port) { 

     SocketChannel socketChannel = null; 
     try { 
      socketChannel = SocketChannel.open(); 
      SocketAddress socketAddress = new InetSocketAddress(ip, port); 
      socketChannel.connect(socketAddress); 
      System.out.println("Connected, now sending the file..."); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return socketChannel; 
    } 

    public void sendFile(String fileName) { 
     RandomAccessFile aFile = null; 
     try { 
      File file = new File(fileName); 
      aFile = new RandomAccessFile(file, "r"); 
      FileChannel inChannel = aFile.getChannel(); 

      long bytesSent = 0, fileLength = file.length(); 
      System.out.println("File length: " + fileLength); 
      dos.writeBytes(fileLength + "\n"); 

      // send the file 
      while (bytesSent < fileLength) { 
       bytesSent += inChannel.transferTo(bytesSent, fileLength - bytesSent, socketChannel); 
      } 
      inChannel.close(); 

      Thread.sleep(1000); 
      System.out.println("End of file reached.."); 
      aFile.close(); 
      System.out.println("File closed."); 

     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

    } 

    public String getLink() { 
     return link; 
    } 

} 

ответ

1

Вы теряете данные в BufferedReader. Если вы посмотрите на файл, который был получен, вы увидите, что его часть отсутствует в начале.

Вы не можете смешивать буферный и небуферизованный вход на одном канале. Я предлагаю вам использовать DataInputStream и использовать read/writeUTF() для передачи имени файла и read/writeLong() для передачи длины.

Я не могу себе представить, почему вы используете другой код для передачи изображений и других файлов. Это все байты.

 Смежные вопросы

  • Нет связанных вопросов^_^