0

I have tried sending files using java NIO socket channels according to this guide. It works fine. I modified the method to send List of files. Basically, i loop through the files list and call send method already implemented in the above-mentioned guide. There was an error "Address already in use" so I commented the socket closing line in FileSender class. After that, there was no error in the code. Seems the program stuck in middle. How do I solve this problem? is there any better way to solve the problem?

Main.Java

public static void main(String[] args) throws IOException, InterruptedException{
    RunningConfiguration.run();

    List<File> files = new <File>ArrayList();

    File a = new File("pics/city.jpg");
    File b = new File("pics/desert.jpg");
    File c = new File("pics/flower.jpg");
    File d = new File("pics/night.jpg");

    List<Node> nodes = RunningConfiguration.getNodeList();

    ListIterator li = nodes.listIterator();

    while(li.hasNext()){
        Node node = (Node)li.next();
        FileSender.send(node, files, "pics/received/");
    }

}

FileSender.Java

public class FileSender {
private final InetSocketAddress fileSocketAddress;
private final File file;

public FileSender(InetAddress inetAddress, File file) throws IOException{
    this.fileSocketAddress = new InetSocketAddress(inetAddress,RunningConfiguration.FILE_PORT);
    this.file = file;
}

public static void send(InetSocketAddress inetSocketAddress, File file) throws IOException{
    FileSender nioClient = new FileSender(inetSocketAddress.getAddress(),file);
    SocketChannel socketChannel = nioClient.createChannel();
    nioClient.sendFile(socketChannel);
}

public static void send(Node to, File file) throws IOException{
    FileSender nioClient = new FileSender(to.getSocketAddress().getAddress(),file);
    SocketChannel socketChannel = nioClient.createChannel();
    nioClient.sendFile(socketChannel);
}

public static void send(Node to, File file,String filepath) throws IOException{
    FileSender nioClient = new FileSender(to.getSocketAddress().getAddress(),file);
    SocketChannel socketChannel = nioClient.createChannel();
    nioClient.sendFile(socketChannel);
}

public static void send(Node to,List<File> files,String filepath) throws IOException{
    ListIterator ltr = files.listIterator();
    while(ltr.hasNext()){
        File file = (File) ltr.next();
        FileSender nioClient = new FileSender(to.getSocketAddress().getAddress(),file);
        SocketChannel socketChannel = nioClient.createChannel();
        nioClient.sendFile(socketChannel);
    }
}
public SocketChannel createChannel() {
    SocketChannel socketChannel = null;

    try {
        socketChannel = SocketChannel.open();
        SocketAddress socketAddress = this.fileSocketAddress;
        socketChannel.connect(socketAddress);
        System.out.println("Connected..Now sending the file");
    } catch (IOException e) {
        e.printStackTrace();
    }
    return socketChannel;
}


public void sendFile(SocketChannel socketChannel) {
    RandomAccessFile aFile = null;
    try {
        //File file = new File("data\\web.exe");
        aFile = new RandomAccessFile(this.file, "r");
        FileChannel inChannel = aFile.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        while (inChannel.read(buffer) > 0) {
            buffer.flip();
            socketChannel.write(buffer);
            buffer.clear();
        }

        Thread.sleep(400);
        System.out.println("End of file reached..");
        socketChannel.close();
        aFile.close();

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

FileReceiver.java

private String fileName;

public FileReceiver(String fileName) {
    this.fileName = fileName;
}

public static void receive(String fileName) {
    FileReceiver nioServer = new FileReceiver(fileName);
    SocketChannel socketChannel = nioServer.createServerSocketChannel();
    nioServer.readFileFromSocket(socketChannel);
}

public FileReceiver() {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

public SocketChannel createServerSocketChannel() {

    ServerSocketChannel serverSocketChannel = null;
    SocketChannel socketChannel = null;

    try {
        System.out.println("File receiver listening at port: " + RunningConfiguration.FILE_PORT);
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(RunningConfiguration.FILE_PORT));
        socketChannel = serverSocketChannel.accept();
        System.out.println("Connection established...." + socketChannel.getRemoteAddress());

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

    return socketChannel;
}

/**
 * Reads the bytes from socket and writes to file
 *
 * @param socketChannel
 */
public void readFileFromSocket(SocketChannel socketChannel) {

    RandomAccessFile aFile = null;
    try {
        aFile = new RandomAccessFile(this.fileName, "rw");
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        FileChannel fileChannel = aFile.getChannel();
        while (socketChannel.read(buffer) > 0) {
            buffer.flip();
            fileChannel.write(buffer);
            buffer.clear();
        }
       // Thread.sleep(1000);
        fileChannel.close();
        System.out.println("End of file reached..Closing channel");
        socketChannel.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }/*} catch (InterruptedException e) {
        e.printStackTrace();
    }*/
}
Arunwij
  • 390
  • 1
  • 4
  • 22

1 Answers1

0

You need to send the length, and probably the name, ahead of the file, so the receiver knows when to stop. The receiver has to make sure to only read exactly that many bytes, which may require reducing the limit on the last read. In addition your copy loops are incorrect:

while (inChannel.read(buffer) > 0) {
    buffer.flip();
    socketChannel.write(buffer);
    buffer.clear();
}

This doesn't necessarily work correctly at end of stream. It should be:

while (inChannel.read(buffer) >= 0 || buffer.position() > 0) {
    buffer.flip();
    socketChannel.write(buffer);
    buffer.compact(); // NB compact(), not clear()
}

noting again that they will need further modification as described above.

user207421
  • 305,947
  • 44
  • 307
  • 483