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


    }
}

posted @ 2020-08-24 14:00  半雨微凉  阅读(1839)  评论(0编辑  收藏  举报