使用Java NIO SocketChannel发送多个文件

时间:2017-11-27 16:40:45

标签: java sockets nio socketchannel

我已尝试根据this指南使用java NIO套接字通道发送文件。它工作正常。我修改了方法来发送文件列表。基本上,我遍历文件列表并调用已在上述指南中实现的send方法。有一个错误“地址已在使用中”,所以我评论了FileSender类中的套接字结束行。之后,代码中没有错误。似乎程序卡在中间。我该如何解决这个问题?有没有更好的方法来解决这个问题?

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();
    }*/
}

1 个答案:

答案 0 :(得分:0)

您需要在文件前发送长度,可能还有名称,以便接收方知道何时停止。接收器必须确保只读取那么多字节,这可能需要减少上次读取时的limit。此外,您的副本循环不正确:

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

这不一定在流的末尾正常工作。它应该是:

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

再次注意到他们需要进行如上所述的进一步修改。