NIO文件傳輸

Server端


import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Objects;

/**
 * @decription: 文件傳輸服務端: java Server dir port
 * @author: PENGPANTING740
 * @date: 2019/4/25 16:08
 */
public class Server {

    private static String dir = "C:\\Users\\pengpanting740\\Desktop\\log\\temp";
    private static int port = 8888;
    public static void main(String[] args) throws Exception {
        if (Objects.nonNull(args) && args.length > 0) {
            dir = args[0];
            if (args.length > 1) {
                port = Integer.parseInt(args[1]);
            }
        }
        System.out.println("dir is: " + dir);
        System.out.println("Server start, and listen port is: " + port);
        Selector selector = Selector.open();
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ssc.bind(new InetSocketAddress(port));
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            selector.select();
            Iterator<SelectionKey> it = selector.selectedKeys().iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                if (key.isAcceptable()) {
                    System.out.println("isAcceptable");
                    SocketChannel sc = ssc.accept();
                    sc.configureBlocking(false);
                    sc.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel)key.channel();
                    Protocol p = Protocol.deserialize(socketChannel);
                    if (p.isValid()) {
                        if (p.getAction() == Protocol.Action.PUT) {
                            FileUtils.writeToFile(dir, p.getFileName(), p.getBody());
                            Protocol result = new Protocol();
                            result.setBody("upload is success".getBytes());
                            result.setAction(Protocol.Action.PUT);
                            result.setFileName("ok!");
                            ByteBuffer bb = result.serialize();
                            socketChannel.write(bb);
                        } else if (p.getAction() == Protocol.Action.GET) {
                            ByteBuffer bb = FileUtils.downloadFile(dir, p);
                            socketChannel.write(bb);
                        }
                    }
                    socketChannel.close();
                }
                it.remove();
            }
        }
    }
}

cleint端


import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Objects;

/**
 * @decription: 文件傳輸客戶端: java Client ip port fileName
 * @author: PENGPANTING740
 * @date: 2019/4/25 16:59
 */
public class Client {
    private static String dir = "C:\\Users\\pengpanting740\\Desktop\\log";
    private static String file = "env.txt";
    private static String ip = "localhost";
    private static int port = 8888;
    public static void main(String[] args) throws Exception {
//        ip = "192.168.5.19";
        if (Objects.nonNull(args) && args.length > 0) {
            ip = args[0];
            if (args.length > 1) {
                port = Integer.parseInt(args[1]);
                if (args.length > 2) {
                    file = args[2];
                }
            }
        }
        SocketChannel sc = SocketChannel.open();
        sc.configureBlocking(true);
        sc.connect(new InetSocketAddress(ip, port));
        boolean isUpload = false;
        ByteBuffer buffer;
        if (isUpload) {
            buffer = FileUtils.uploadRequest(dir, file);
        } else {
            buffer = FileUtils.downloadRequest("env.txt");
        }
        sc.write(buffer);
        Protocol p = Protocol.deserialize(sc);
        if (p.getAction() == Protocol.Action.GET) {
            FileUtils.writeToFile(dir, p.getFileName(), p.getBody());
        }
        System.out.println(p);
        sc.close();
    }
}

協議類Protocol


import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Objects;

/**
 * @decription: protocol: 4(totalLength):1(action):2(fileNameLength):change(fileName):change(body)
 * @author: PENGPANTING740
 * @date: 2019/4/26 15:46
 */
public class Protocol {
    private Action action = Action.PUT;
    private String fileName;
    private byte[] body;
    private boolean isValid;

    public ByteBuffer serialize() {
        if (Objects.isNull(this.fileName) || Objects.isNull(this.action)) {
            throw new RuntimeException("fileName and action can not be null.");
        }
        int totalLength = 4 + 1 + 2 + this.fileName.length();
        if (Objects.nonNull(this.body)) {
            totalLength += this.body.length;
        }
        ByteBuffer buffer = ByteBuffer.allocate(totalLength);
        buffer.putInt(totalLength);
        buffer.put((byte)action.ordinal());
        buffer.putShort((short)this.fileName.length());
        buffer.put(this.fileName.getBytes());
        if (Objects.nonNull(this.body)) {
            buffer.put(this.body);
        }
        buffer.flip();
        return buffer;
    }
    public static Protocol deserialize(SocketChannel channel) throws Exception {
        Protocol p = new Protocol();
        ByteBuffer totalLengthBuffer = ByteBuffer.allocate(4);
        int length = -1;
        while (totalLengthBuffer.hasRemaining()) {
            length = channel.read(totalLengthBuffer);
            if (length < 0) {
                break;
            }
            Thread.sleep(5);
        }
        if (length > -1) {
            totalLengthBuffer.flip();
            int totalLength = totalLengthBuffer.getInt();
            ByteBuffer totalBuffer = ByteBuffer.allocate(totalLength - 4);
            while (totalBuffer.hasRemaining()) {
                length = channel.read(totalBuffer);
                if (length < 0) {
                    break;
                }
                Thread.sleep(5);
            }
            if (length > -1) {
                totalBuffer.flip();
                byte action = totalBuffer.get();
                short fileNameLength = totalBuffer.getShort();
                byte[] fileName = new byte[fileNameLength];
                totalBuffer.get(fileName);
                int bodyLength = totalLength - 4 - 1 - 2 - fileNameLength;
                if (bodyLength > 0) {
                    byte[] content = new byte[bodyLength];
                    totalBuffer.get(content);
                    p.setBody(content);
                }
                switch (action) {
                    case 0:
                        p.setAction(Action.GET);
                        break;
                    case 1:
                        p.setAction(Action.PUT);
                        break;
                    default:
                        System.out.println("invalid action: " + action);
                        break;
                }
                p.setFileName(new String(fileName));
                p.setValid(true);
            }
        } else {
            channel.close();
        }
        return p;
    }

    public boolean isValid() {
        return isValid;
    }

    public void setValid(boolean valid) {
        isValid = valid;
    }

    public Action getAction() {
        return action;
    }

    public void setAction(Action action) {
        this.action = action;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    @Override
    public String toString() {
        return "Protocol{" +
                "action=" + action +
                ", fileName='" + fileName + '\'' +
                ", isValid=" + isValid +
                '}';
    }

    static enum Action {
        GET,
        PUT
        ;
    }
}

工具類FileUtils


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;

/**
 * @decription: TODO
 * @author: PENGPANTING740
 * @date: 2019/4/26 17:05
 */
public class FileUtils {

    public static void writeToFile(String dir, String fileName, byte[] content) throws Exception {
        System.out.println("write file name: " + fileName + " and body length: " + content.length);
        FileOutputStream fos = new FileOutputStream(dir + File.separator + fileName);
        fos.write(content);
        fos.close();
    }

    public static ByteBuffer downloadFile(String dir, Protocol p) throws Exception {
        String fileName = p.getFileName();
        FileInputStream fis = new FileInputStream(dir + File.separator + fileName);
        int bodyLength = fis.available();
        byte[] body = new byte[bodyLength];
        fis.read(body);
        fis.close();
        p.setBody(body);
        System.out.println("download file name: " + fileName + " and body length: " + bodyLength);
        return p.serialize();
    }

    public static ByteBuffer uploadRequest(String dir, String fileName) throws Exception {
        FileInputStream fis = new FileInputStream(dir + File.separator + fileName);
        int bodyLength = fis.available();
        byte[] body = new byte[bodyLength];
        fis.read(body);
        fis.close();
        Protocol p = new Protocol();
        p.setFileName(fileName);
        p.setBody(body);
        p.setAction(Protocol.Action.PUT);
        ByteBuffer buffer = p.serialize();
        return buffer;
    }

    public static ByteBuffer downloadRequest(String fileName) throws Exception {
        Protocol p = new Protocol();
        p.setFileName(fileName);
        p.setAction(Protocol.Action.GET);
        ByteBuffer buffer = p.serialize();
        return buffer;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章