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


    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM