如何写TFTP-UDP 的服务器和客户端,基于RFC1350

基于RFC1350,怎么写TFTP-UDP服务器和客户端。用Java

要编写TFTP-UDP服务器和客户端,您需要遵循RFC1350中定义的TFTP协议规范。TFTP是基于UDP协议的简单文件传输协议,其使用的端口号为69。在Java中,您可以使用Java Socket API来实现TFTP客户端和服务器。下面是一些步骤,可以帮助您开始编写TFTP-UDP服务器和客户端。

TFTP-UDP服务器:


import java.net.*;
import java.io.*;

public class TFTPServer {
    private static final int SERVER_PORT = 69;

    public static void main(String[] args) throws Exception {
        //创建一个Java程序来接收来自TFTP客户端的UDP数据包。
        DatagramSocket serverSocket = new DatagramSocket(SERVER_PORT);
        System.out.println("TFTP server is running on port " + SERVER_PORT);

        while (true) {
            byte[] receiveData = new byte[516];
//建一个DatagramPacket对象来保存接收到的数据包。
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            serverSocket.receive(receivePacket);
            new Thread(new TFTPServerThread(receivePacket)).start();
        }
    }
}

class TFTPServerThread implements Runnable {
    private DatagramPacket receivePacket;

    public TFTPServerThread(DatagramPacket receivePacket) {
        this.receivePacket = receivePacket;
    }

    public void run() {
        try {
            DatagramSocket socket = new DatagramSocket();
            InetAddress clientAddress = receivePacket.getAddress();
            int clientPort = receivePacket.getPort();

            byte[] data = receivePacket.getData();
            if (data[1] == 1) { // RRQ (read request)
                String fileName = new String(data, 2, receivePacket.getLength() - 3);
                System.out.println("Received RRQ for file " + fileName);

                File file = new File(fileName);
                if (!file.exists()) {
                    byte[] errorData = {0, 5, 0, 1, 'F', 'i', 'l', 'e', ' ', 'n', 'o', 't', ' ', 'f', 'o', 'u', 'n', 'd', 0};
                    DatagramPacket errorPacket = new DatagramPacket(errorData, errorData.length, clientAddress, clientPort);
                    socket.send(errorPacket);
                    System.out.println("File not found error sent");
                    return;
                }

                FileInputStream fileInputStream = new FileInputStream(file);
                byte[] fileData = new byte[(int)file.length()];
                fileInputStream.read(fileData);
                fileInputStream.close();

                int blockNum = 1;
                int offset = 0;
                while (offset < fileData.length) {
                    byte[] sendData = new byte[516];
                    sendData[0] = 0;
                    sendData[1] = 3;
                    sendData[2] = (byte)(blockNum >> 8);
                    sendData[3] = (byte)blockNum;
                    int length = Math.min(fileData.length - offset, 512);
                    System.arraycopy(fileData, offset, sendData, 4, length);
                    DatagramPacket sendPacket = new DatagramPacket(sendData, length + 4, clientAddress, clientPort);
                    socket.send(sendPacket);

                    byte[] receiveData = new byte[516];
                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    socket.receive(receivePacket);
                    if (receiveData[1] != 4 || receiveData[2] != sendData[2] || receiveData[3] != sendData[3]) {
                        System.out.println("ACK mismatch, expected block " + blockNum);
                        continue;
                    }
                    blockNum++;
                    offset += length;
                }
                System.out.println("File transfer completed");
            } else         if (data[1] == 2) { // WRQ (write request)
            String fileName = new String(data, 2, receivePacket.getLength() - 3);
            System.out.println("Received WRQ for file " + fileName);

            File file = new File(fileName);
            if (file.exists()) {
                byte[] errorData = {0, 5, 0, 6, 'F', 'i', 'l', 'e', ' ', 'a', 'l', 'r', 'e', 'a', 'd', 'y', ' ', 'e', 'x', 'i', 's', 't', 's', 0};
                DatagramPacket errorPacket = new DatagramPacket(errorData, errorData.length, clientAddress, clientPort);
                socket.send(errorPacket);
                System.out.println("File already exists error sent");
                return;
            }

            FileOutputStream fileOutputStream = new FileOutputStream(file);
            int blockNum = 0;
            byte[] sendData = new byte[4];
            sendData[0] = 0;
            sendData[1] = 4;
            sendData[2] = 0;
            sendData[3] = 0;
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, clientAddress, clientPort);
            socket.send(sendPacket);

            while (true) {
                byte[] receiveData = new byte[516];
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                socket.receive(receivePacket);
                if (receiveData[1] != 3 || receiveData[2] != (byte)(blockNum >> 8) || receiveData[3] != (byte)blockNum) {
                    byte[] errorData = {0, 5, 0, 4, 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ', 'b', 'l', 'o', 'c', 'k', ' ', 'n', 'u', 'm', 'b', 'e', 'r', 0};
                    DatagramPacket errorPacket = new DatagramPacket(errorData, errorData.length, clientAddress, clientPort);
                    socket.send(errorPacket);
                    System.out.println("Invalid block number error sent, expected block " + blockNum);
                    continue;
                }
                int length = receivePacket.getLength() - 4;
                fileOutputStream.write(receiveData, 4, length);

                sendData[2] = (byte)(blockNum >> 8);
                sendData[3] = (byte)blockNum;
                sendPacket.setData(sendData);
                sendPacket.setLength(sendData.length);
                socket.send(sendPacket);

                if (length < 512) {
                    break;
                }
                blockNum++;
            }
            fileOutputStream.close();
            System.out.println("File transfer completed");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}



TFTP-UDP客户端:

```java
import java.net.*;
import java.io.*;

public class TFTPClient {
    private static final int SERVER_PORT = 69;

    public static void main(String[] args) throws Exception {
        if (args.length != 3) {
            System.out.println("Usage: java TFTPClient <server> <get/put> <file>");
            return;
        }

        String serverAddress = args[0];
        String operation = args[1];
        String fileName = args[2];

        DatagramSocket socket = new DatagramSocket();
        InetAddress serverInetAddress = InetAddress.getByName(serverAddress);

        //byte[] data = new byte[516];
        //data[0] = 0;
    if ("put".equals(operation)) {
        FileInputStream fileInputStream = new FileInputStream(fileName);
        int blockNum = 0;
        byte[] sendData = new byte[516];
        sendData[0] = 0;
        sendData[1] = 2;
        byte[] fileNameBytes = fileName.getBytes();
        System.arraycopy(fileNameBytes, 0, sendData, 2, fileNameBytes.length);
        sendData[fileNameBytes.length + 2] = 0;
        byte[] modeBytes = "octet".getBytes();
        System.arraycopy(modeBytes, 0, sendData, fileNameBytes.length + 3, modeBytes.length);
        sendData[fileNameBytes.length + modeBytes.length + 3] = 0;

        DatagramPacket sendPacket = new DatagramPacket(sendData, fileNameBytes.length + modeBytes.length + 4, serverInetAddress, SERVER_PORT);
        socket.send(sendPacket);

        while (true) {
            byte[] receiveData = new byte[516];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            socket.receive(receivePacket);
            if (receiveData[1] != 4 || receiveData[2] != (byte)(blockNum >> 8) || receiveData[3] != (byte)blockNum) {
                throw new Exception("Invalid ACK received, expected ACK for block " + blockNum);
            }

            if (fileInputStream.available() > 0) {
                int length = fileInputStream.read(sendData, 4, 512);
                sendData[0] = 0;
                sendData[1] = 3;
                sendData[2] = (byte)(blockNum >> 8);
                sendData[3] = (byte)blockNum;

                sendPacket.setData(sendData);
                sendPacket.setLength(length + 4);
                socket.send(sendPacket);
                blockNum++;

                if (length < 512) {
                    break;
                }
            } else {
                break;
            }
        }
        fileInputStream.close();
        System.out.println("File transfer completed");
    } else if ("get".equals(operation)) {
        FileOutputStream fileOutputStream = new FileOutputStream(fileName);
        int blockNum = 0;
        byte[] sendData = new byte[516];
        sendData[0] = 0;
        sendData[1] = 1;
        byte[] fileNameBytes = fileName.getBytes();
        System.arraycopy(fileNameBytes, 0, sendData, 2, fileNameBytes.length);
        sendData[fileNameBytes.length + 2] = 0;
        byte[] modeBytes = "octet".getBytes();
        System.arraycopy(modeBytes, 0, sendData, fileNameBytes.length + 3, modeBytes.length);
        sendData[fileNameBytes.length + modeBytes.length + 3] = 0;

        DatagramPacket sendPacket = new DatagramPacket(sendData, fileNameBytes.length + modeBytes.length + 4, serverInetAddress, SERVER_PORT);
        socket.send(sendPacket);

        while (true) {
            byte[] receiveData = new byte[516];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            socket.receive(receivePacket);
            if (receiveData[1] != 3 || receiveData[2] != (byte)(blockNum >> 8) || receiveData[3] != (byte)blockNum) {
                throw new Exception("Invalid data block received, expected block " + blockNum);
            }

            int length = receivePacket.getLength() - 4;
            fileOutputStream.write(receiveData, 4, length);

            byte[] ackData = {0, 4, (byte)(blockNum >> 8), (byte)blockNum};
            DatagramPacket ackPacket            = new DatagramPacket(ackData, ackData.length, serverInetAddress, receivePacket.getPort());
            socket.send(ackPacket);

            blockNum++;
            if (length < 512) {
                break;
            }
        }
        fileOutputStream.close();
        System.out.println("File transfer completed");
    }
}



上述代码实现了一个基本的TFTP客户端。您可以通过将“get”或“put”作为第一个参数传递给该程序来指定要执行的操作。在“put”操作中,客户端将文件从本地计算机传输到TFTP服务器,而在“get”操作中,客户端从TFTP服务器获取文件并将其保存到本地计算机中。

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632