zoukankan      html  css  js  c++  java
  • JAVA使用UDP收发文件

    java使用UDP发送文件

    环境

    maven 3.6

    jdk 1.8

    下载源码

    码云项目地址

    udp-nio 分支支持批量发送

    2021-05-10 udp-nio分支代码已废弃

    请参考 udp-etty 分支代码

    服务端源码(接收文件)

    package com.banywl.file.transfer.udp;
    
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    
    /**
     * 文件接收服务器
     */
    public class UDPFileServer {
    
        /**
         * socket 缓冲区
         */
        private DatagramSocket socket;
        /**
         * 文件包数据大小
         */
        private int packetSize;
        /**
         * 名称长度值占用4字节
         * 文件长度值占用8字节
         */
        private byte[] fileInfo = new byte[12];
        /**
         * packet 缓冲区
         */
        private byte[] packetBuf;
        /**
         * 文件名长度值用4字节缓冲区接收 int 值
         */
        private DatagramPacket fileNameLenPacket;
        /**
         * 文件长度值使用8字节缓冲区接收 long 值
         */
        private DatagramPacket fileLenPacket;
        /**
         * 文件数据封包使用512字节缓冲区分段接收
         */
        private DatagramPacket filePacket;
        /**
         * 接收到的文件名
         */
        private String fileName;
        /**
         * 接收到的文件内容
         */
        private byte[] fileData;
    
    
        /**
         * 初始化文件接收UDP服务
         *
         * @param port 监听端口
         * @param packetSize 封包大小
         * @throws SocketException
         */
        public UDPFileServer(int port, int packetSize) throws SocketException {
            this.socket = new DatagramSocket(port);
            this.packetSize = packetSize;
            this.packetBuf = new byte[packetSize];
    
    
            fileNameLenPacket = new DatagramPacket(fileInfo,  4);
            fileLenPacket = new DatagramPacket(fileInfo,  4,8);
            filePacket = new DatagramPacket(packetBuf,  this.packetSize);
        }
    
        /**
         * 接收文件,
         * udp 包顺序: 1、文件名长度值 2、文件长度值 3、文件名 4、文件内容
         *
         * @return 文件内容字节数组
         * @throws IOException
         */
        public void receiveFile() throws IOException {
            // 读取文件名长度
            this.socket.receive(fileNameLenPacket);
            // 读取文件长度
            this.socket.receive(fileLenPacket);
            // 取回文件名
            byte[] fileNameBuf = new byte[Utils.bytesToInt(this.fileInfo)];
            DatagramPacket fnPacket = new DatagramPacket(fileNameBuf, fileNameBuf.length);
            this.socket.receive(fnPacket);
            this.fileName = new String(fileNameBuf);
            // 建立文件缓冲区,读取文件内容到缓冲区
            int fileLen = (int) Utils.bytesToLong(this.fileInfo,4);
            this.fileData = new byte[fileLen];
            int writePos = 0;
            while (writePos != fileLen) {
                // 取回文件内容
                this.socket.receive(filePacket);
                if (writePos + this.packetSize < fileLen) {
                    System.arraycopy(packetBuf, 0, this.fileData, writePos, this.packetSize);
                    writePos += this.packetSize;
                } else {
                    int rsize = fileLen - writePos;
                    System.arraycopy(packetBuf, 0, this.fileData, writePos, rsize);
                    writePos += rsize;
                }
                System.out.println(String.format("已接收:%.4f",(double)writePos / (double) fileLen));
            }
            System.out.println("接收完成");
        }
    
        public void close() {
            this.socket.close();
        }
    
    
        public String getFileName() {
            return fileName;
        }
    
        public byte[] getFileData() {
            return fileData;
        }
    
    
    }
    
    

    UDP客户端源码(发送文件)

    package com.banywl.file.transfer.udp;
    
    import java.io.*;
    import java.net.*;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 文件发送客户端
     */
    public class UDPFileClient {
    
        private InetAddress address;
    
        private int port;
        /**
         * 包大小
         */
        private int packetSize;
        /**
         * 文件包
         */
        private byte[] packetBuf;
        /**
         * 名称长度值占用4字节
         * 文件长度值占用8字节
         */
        private byte[] fileInfoBuf = new byte[12];
    
        /**
         * 文件名 packet
         */
        private DatagramPacket fileNameLenPacket;
        /**
         * 文件长度 packet
         */
        private DatagramPacket fileLenPacket;
        /**
         * 文件数据 packet
         */
        private DatagramPacket filePacket;
    
        private DatagramSocket socket = new DatagramSocket();
    
        /**
         * 初始化文件发送
         * @param hostname 目标主机名称
         * @param port 目标端口
         * @param packetSize 封包大小
         * @throws UnknownHostException
         * @throws SocketException
         */
        public UDPFileClient(String hostname, int port,int packetSize) throws UnknownHostException, SocketException {
            this.address = InetAddress.getByName(hostname);
            this.port = port;
            this.packetSize = packetSize;
            this.packetBuf = new byte[this.packetSize];
            // 文件名长度值用4字节
            this.fileNameLenPacket = new DatagramPacket(this.fileInfoBuf,4,this.address,port);
            // 文件长度使用8字节
            this.fileLenPacket = new DatagramPacket(this.fileInfoBuf,4,8,this.address,port);
            // 文件使用512字节分段发送
            this.filePacket = new DatagramPacket(packetBuf,this.packetSize,this.address,port);
        }
    
        /**
         * udp 包顺序: 1、文件名长度值 2、文件长度值 3、文件名 4、文件内容
         * @param filePath 文件路径
         * @throws IOException
         */
        public void sendFile(String filePath) throws IOException {
            // 读取系统文件
            File file = new File(filePath);
            byte[] fileBuf = new byte[(int)file.length()];
            byte[] readBuf = new byte[2048];
            int readLen,staPos = 0;
            FileInputStream inputStream =new FileInputStream(file);
            while ((readLen = inputStream.read(readBuf))!=-1){
                System.arraycopy(readBuf,0,fileBuf,staPos,readLen);
                staPos += readLen;
            }
            // 发送文件名长度值和文件长度值
            System.arraycopy(Utils.intToBytes(file.getName().getBytes().length),0,this.fileInfoBuf,0,4);
            System.arraycopy(Utils.longToBytes(file.length()),0,this.fileInfoBuf,4,8);
            socket.send(fileNameLenPacket);
            socket.send(fileLenPacket);
            // 发送文件名
            DatagramPacket fileNamPacket = new DatagramPacket(file.getName().getBytes(),file.getName().getBytes().length,address,port);
            socket.send(fileNamPacket);
    
            // 发送文件
            int readIndex = 0;
            while (readIndex != fileBuf.length){
                if(readIndex + this.packetSize < fileBuf.length){
                    System.arraycopy(fileBuf,readIndex,packetBuf,0,this.packetSize);
                    readIndex += this.packetSize;
                }else{
                    int rsize = fileBuf.length - readIndex;
                    System.arraycopy(fileBuf,readIndex,packetBuf,0,rsize);
                    readIndex += rsize;
                }
                socket.send(filePacket);
                System.out.println(String.format("已发送:%.4f",(double)readIndex / (double) file.length()));
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("发送完成");
        }
        public void close(){
            this.socket.close();
        }
    
    
    
    
    }
    
    

    例子(Application.java)

    
    package com.banywl.file.transfer.udp;
    
    import java.io.*;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    
    public class Application {
    
        /**
         * -server 18888 10240
         * -client 255.255.255.255 18888 10240 path/to/file
         * @param args
         */
        public static void main(String[] args) {
            String baseDir = System.getProperty("user.dir") ;
            System.out.println(baseDir);
            if (args.length == 0) {
                System.out.println("参数错误!");
                System.exit(0);
            }
    
            if ("-server".equals(args[0])) {
                System.out.println("启动服务端");
                int port = Integer.parseInt(args[1]);
                int size = args.length == 2 ? 1024 : Integer.parseInt(args[2]);
    
                try {
                    UDPFileServer server = new UDPFileServer(port,size);
                    while (true){
                        System.out.println("等待接收");
                        server.receiveFile();
                        System.out.println("收到文件:"+ server.getFileName());
                        File file = new File(baseDir + File.separator+ "receive" + File.separator+server.getFileName());
                        if (!file.getParentFile().exists()){
                            file.getParentFile().mkdir();
                        }
                        FileOutputStream fo = new FileOutputStream(file);
                        fo.write(server.getFileData());
                        fo.close();
                        System.out.println("是否退出(Y/N)?");
                        Scanner scanner = new Scanner(System.in);
                        if ("y".equalsIgnoreCase(scanner.next())){
                            break;
                        }
                    }
                    server.close();
                    System.out.println("服务器已关闭");
                } catch (SocketException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else if("-client".equals(args[0])){
                System.out.println("启动客户端");
                String ip = args[1];
                int port = Integer.parseInt(args[2]);
                int size = Integer.parseInt(args[3]);
                String pathname = args[4];
                try {
                    UDPFileClient client = new UDPFileClient(ip,port,size);
                    client.sendFile(pathname);
                    client.close();
                    System.out.println("发送完成");
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (SocketException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
    
        }
    }
    
    
  • 相关阅读:
    vue项目开发基本目录结构
    小程序图片上传七牛
    vue2.0无限滚动加载数据插件
    Vue使用vue-echarts图表
    vue-countTo---简单好用的一个数字滚动插件
    vee-validate的使用
    javaScript---RegExp
    JavaScript 特效之四大家族(offset/scroll/client/event)
    CSS3 三次贝塞尔曲线(cubic-bezier)
    require和import区别
  • 原文地址:https://www.cnblogs.com/banywl/p/13553518.html
Copyright © 2011-2022 走看看