首页

使用apache的commons-net包中的TFTPClient类基于TFTP文件传输协议的实现源码分析说明

标签:tftp,apache,commons-net,DatagramSocket,TFTPClient     发布时间:2018-02-21   

一、前言

基于apachecommons-net开源包中的org.apache.commons.net.tftp.TFTPClient、org.apache.commons.net.tftp.TFTP类,实现了基于tftp文件传输协议的客户端调用访问,详情参见下面源码说明。

二、源码说明

1.TFTPClient类

package org.apache.commons.net.tftp;@b@@b@import java.io.IOException;@b@import java.io.InputStream;@b@import java.io.InterruptedIOException;@b@import java.io.OutputStream;@b@import java.net.InetAddress;@b@import java.net.SocketException;@b@import java.net.UnknownHostException;@b@import org.apache.commons.net.io.FromNetASCIIOutputStream;@b@import org.apache.commons.net.io.ToNetASCIIInputStream;@b@@b@public class TFTPClient extends TFTP@b@{@b@  public static final int DEFAULT_MAX_TIMEOUTS = 5;@b@  private int __maxTimeouts;@b@@b@  public TFTPClient()@b@  {@b@    this.__maxTimeouts = 5;@b@  }@b@@b@  public void setMaxTimeouts(int numTimeouts)@b@  {@b@    if (numTimeouts < 1)@b@      this.__maxTimeouts = 1;@b@    else@b@      this.__maxTimeouts = numTimeouts;@b@  }@b@@b@  public int getMaxTimeouts()@b@  {@b@    return this.__maxTimeouts;@b@  }@b@@b@  public int receiveFile(String filename, int mode, OutputStream output, InetAddress host, int port)@b@    throws IOException@b@  {@b@    int bytesRead;@b@    int lastBlock;@b@    int hostPort;@b@    TFTPPacket received = null;@b@@b@    TFTPAckPacket ack = new TFTPAckPacket(host, port, 0);@b@@b@    beginBufferedOps();@b@@b@    int dataLength = lastBlock = hostPort = bytesRead = 0;@b@    int block = 1;@b@@b@    if (mode == 0)@b@      output = new FromNetASCIIOutputStream(output);@b@@b@    TFTPPacket sent = new TFTPReadRequestPacket(host, port, filename, mode);@b@    do@b@    {@b@      bufferedSend(sent);@b@      do@b@      {@b@        int timeouts = 0;@b@        if (timeouts < this.__maxTimeouts)@b@        {@b@          try@b@          {@b@            received = bufferedReceive();@b@          }@b@          catch (SocketException e)@b@          {@b@            while (true)@b@              if (++timeouts >= this.__maxTimeouts)@b@              {@b@                endBufferedOps();@b@                throw new IOException("Connection timed out.");@b@              }@b@          }@b@          catch (InterruptedIOException e)@b@          {@b@            while (true)@b@              if (++timeouts >= this.__maxTimeouts)@b@              {@b@                endBufferedOps();@b@                throw new IOException("Connection timed out.");@b@              }@b@@b@          }@b@          catch (TFTPPacketException e)@b@          {@b@            endBufferedOps();@b@            throw new IOException("Bad packet: " + e.getMessage());@b@          }@b@@b@        }@b@@b@        if (lastBlock == 0)@b@        {@b@          hostPort = received.getPort();@b@          ack.setPort(hostPort);@b@          if (!(host.equals(received.getAddress())))@b@          {@b@            host = received.getAddress();@b@            ack.setAddress(host);@b@            sent.setAddress(host);@b@          }@b@@b@        }@b@@b@        if ((!(host.equals(received.getAddress()))) || (received.getPort() != hostPort)) {@b@          break label485;@b@        }@b@@b@        switch (received.getType())@b@        {@b@        case 5:@b@          error = (TFTPErrorPacket)received;@b@          endBufferedOps();@b@          throw new IOException("Error code " + error.getError() + " received: " + error.getMessage());@b@        case 3:@b@          TFTPDataPacket data = (TFTPDataPacket)received;@b@          dataLength = data.getDataLength();@b@@b@          lastBlock = data.getBlockNumber();@b@@b@          if (lastBlock == block)@b@          {@b@            try@b@            {@b@              output.write(data.getData(), data.getDataOffset(), dataLength);@b@            }@b@            catch (IOException e)@b@            {@b@              error = new TFTPErrorPacket(host, hostPort, 3, "File write failed.");@b@@b@              bufferedSend(error);@b@              endBufferedOps();@b@              throw e;@b@            }@b@            ++block;@b@            if (block <= 65535)@b@              break label516;@b@@b@            block = 0; break label516:@b@          }@b@@b@          discardPackets(); }@b@      }@b@      while (lastBlock != ((block == 0) ? 65535 : block - 1));@b@      continue;@b@@b@      endBufferedOps();@b@      throw new IOException("Received unexpected packet type.");@b@@b@      label485: TFTPErrorPacket error = new TFTPErrorPacket(received.getAddress(), received.getPort(), 5, "Unexpected host or port.");@b@@b@      bufferedSend(error);@b@      continue;@b@@b@      label516: ack.setBlockNumber(lastBlock);@b@      sent = ack;@b@      bytesRead += dataLength;@b@    }@b@@b@    while (dataLength == 512);@b@@b@    bufferedSend(sent);@b@    endBufferedOps();@b@@b@    return bytesRead;@b@  }@b@@b@  public int receiveFile(String filename, int mode, OutputStream output, String hostname, int port)@b@    throws UnknownHostException, IOException@b@  {@b@    return receiveFile(filename, mode, output, InetAddress.getByName(hostname), port);@b@  }@b@@b@  public int receiveFile(String filename, int mode, OutputStream output, InetAddress host)@b@    throws IOException@b@  {@b@    return receiveFile(filename, mode, output, host, 69);@b@  }@b@@b@  public int receiveFile(String filename, int mode, OutputStream output, String hostname)@b@    throws UnknownHostException, IOException@b@  {@b@    return receiveFile(filename, mode, output, InetAddress.getByName(hostname), 69);@b@  }@b@@b@  public void sendFile(String filename, int mode, InputStream input, InetAddress host, int port)@b@    throws IOException@b@  {@b@    int bytesRead;@b@    int lastBlock;@b@    int hostPort;@b@    int totalThisPacket;@b@    TFTPPacket received = null;@b@@b@    TFTPDataPacket data = new TFTPDataPacket(host, port, 0, this._sendBuffer, 4, 0);@b@@b@    boolean justStarted = true;@b@@b@    beginBufferedOps();@b@@b@    int dataLength = lastBlock = hostPort = bytesRead = totalThisPacket = 0;@b@    int block = 0;@b@    boolean lastAckWait = false;@b@@b@    if (mode == 0)@b@      input = new ToNetASCIIInputStream(input);@b@@b@    TFTPPacket sent = new TFTPWriteRequestPacket(host, port, filename, mode);@b@    do@b@    {@b@      bufferedSend(sent);@b@      do@b@      {@b@        int timeouts = 0;@b@        if (timeouts < this.__maxTimeouts)@b@        {@b@          try@b@          {@b@            received = bufferedReceive();@b@          }@b@          catch (SocketException e)@b@          {@b@            while (true)@b@              if (++timeouts >= this.__maxTimeouts)@b@              {@b@                endBufferedOps();@b@                throw new IOException("Connection timed out.");@b@              }@b@          }@b@          catch (InterruptedIOException e)@b@          {@b@            while (true)@b@              if (++timeouts >= this.__maxTimeouts)@b@              {@b@                endBufferedOps();@b@                throw new IOException("Connection timed out.");@b@              }@b@@b@          }@b@          catch (TFTPPacketException e)@b@          {@b@            endBufferedOps();@b@            throw new IOException("Bad packet: " + e.getMessage());@b@          }@b@@b@        }@b@@b@        if (justStarted)@b@        {@b@          justStarted = false;@b@          hostPort = received.getPort();@b@          data.setPort(hostPort);@b@          if (!(host.equals(received.getAddress())))@b@          {@b@            host = received.getAddress();@b@            data.setAddress(host);@b@            sent.setAddress(host);@b@          }@b@@b@        }@b@@b@        if ((!(host.equals(received.getAddress()))) || (received.getPort() != hostPort)) {@b@          break label453;@b@        }@b@@b@        switch (received.getType())@b@        {@b@        case 5:@b@          error = (TFTPErrorPacket)received;@b@          endBufferedOps();@b@          throw new IOException("Error code " + error.getError() + " received: " + error.getMessage());@b@        case 4:@b@          TFTPAckPacket ack = (TFTPAckPacket)received;@b@@b@          lastBlock = ack.getBlockNumber();@b@@b@          if (lastBlock == block)@b@          {@b@            ++block;@b@            if (block > 65535)@b@            {@b@              block = 0;@b@            }@b@            if (!(lastAckWait))@b@              break label484;@b@            break label586:@b@          }@b@@b@          discardPackets(); }@b@      }@b@      while (lastBlock != ((block == 0) ? 65535 : block - 1));@b@      continue;@b@@b@      endBufferedOps();@b@      throw new IOException("Received unexpected packet type.");@b@@b@      label453: TFTPErrorPacket error = new TFTPErrorPacket(received.getAddress(), received.getPort(), 5, "Unexpected host or port.");@b@@b@      bufferedSend(error);@b@      continue;@b@@b@      label484: dataLength = 512;@b@      int offset = 4;@b@      totalThisPacket = 0;@b@@b@      while (dataLength > 0) { if ((bytesRead = input.read(this._sendBuffer, offset, dataLength)) <= 0)@b@          break;@b@        offset += bytesRead;@b@        dataLength -= bytesRead;@b@        totalThisPacket += bytesRead;@b@      }@b@@b@      if (totalThisPacket < 512)@b@      {@b@        lastAckWait = true;@b@      }@b@      data.setBlockNumber(block);@b@      data.setData(this._sendBuffer, 4, totalThisPacket);@b@      sent = data;@b@    }@b@    while ((totalThisPacket > 0) || (lastAckWait));@b@@b@    label586: endBufferedOps();@b@  }@b@@b@  public void sendFile(String filename, int mode, InputStream input, String hostname, int port)@b@    throws UnknownHostException, IOException@b@  {@b@    sendFile(filename, mode, input, InetAddress.getByName(hostname), port);@b@  }@b@@b@  public void sendFile(String filename, int mode, InputStream input, InetAddress host)@b@    throws IOException@b@  {@b@    sendFile(filename, mode, input, host, 69);@b@  }@b@@b@  public void sendFile(String filename, int mode, InputStream input, String hostname)@b@    throws UnknownHostException, IOException@b@  {@b@    sendFile(filename, mode, input, InetAddress.getByName(hostname), 69);@b@  }@b@}

2.TFTP类

package org.apache.commons.net.tftp;@b@@b@import java.io.IOException;@b@import java.io.InterruptedIOException;@b@import java.net.DatagramPacket;@b@import java.net.DatagramSocket;@b@import java.net.SocketException;@b@import org.apache.commons.net.DatagramSocketClient;@b@@b@public class TFTP extends DatagramSocketClient@b@{@b@  public static final int ASCII_MODE = 0;@b@  public static final int NETASCII_MODE = 0;@b@  public static final int BINARY_MODE = 1;@b@  public static final int IMAGE_MODE = 1;@b@  public static final int OCTET_MODE = 1;@b@  public static final int DEFAULT_TIMEOUT = 5000;@b@  public static final int DEFAULT_PORT = 69;@b@  static final int PACKET_SIZE = 516;@b@  private byte[] __receiveBuffer;@b@  private DatagramPacket __receiveDatagram;@b@  private DatagramPacket __sendDatagram;@b@  byte[] _sendBuffer;@b@@b@  public static final String getModeName(int mode)@b@  {@b@    return TFTPRequestPacket._modeStrings[mode];@b@  }@b@@b@  public TFTP()@b@  {@b@    setDefaultTimeout(5000);@b@    this.__receiveBuffer = null;@b@    this.__receiveDatagram = null;@b@  }@b@@b@  public final void discardPackets()@b@    throws IOException@b@  {@b@    DatagramPacket datagram = new DatagramPacket(new byte[516], 516);@b@@b@    int to = getSoTimeout();@b@    setSoTimeout(1);@b@    try@b@    {@b@      this._socket_.receive(datagram);@b@    }@b@    catch (SocketException e)@b@    {@b@      break label42: } catch (InterruptedIOException e) {@b@    }@b@    label42: setSoTimeout(to);@b@  }@b@@b@  public final TFTPPacket bufferedReceive()@b@    throws IOException, InterruptedIOException, SocketException, TFTPPacketException@b@  {@b@    this.__receiveDatagram.setData(this.__receiveBuffer);@b@    this.__receiveDatagram.setLength(this.__receiveBuffer.length);@b@    this._socket_.receive(this.__receiveDatagram);@b@@b@    return TFTPPacket.newTFTPPacket(this.__receiveDatagram);@b@  }@b@@b@  public final void bufferedSend(TFTPPacket packet)@b@    throws IOException@b@  {@b@    this._socket_.send(packet._newDatagram(this.__sendDatagram, this._sendBuffer));@b@  }@b@@b@  public final void beginBufferedOps()@b@  {@b@    this.__receiveBuffer = new byte[516];@b@    this.__receiveDatagram = new DatagramPacket(this.__receiveBuffer, this.__receiveBuffer.length);@b@@b@    this._sendBuffer = new byte[516];@b@    this.__sendDatagram = new DatagramPacket(this._sendBuffer, this._sendBuffer.length);@b@  }@b@@b@  public final void endBufferedOps()@b@  {@b@    this.__receiveBuffer = null;@b@    this.__receiveDatagram = null;@b@    this._sendBuffer = null;@b@    this.__sendDatagram = null;@b@  }@b@@b@  public final void send(TFTPPacket packet)@b@    throws IOException@b@  {@b@    this._socket_.send(packet.newDatagram());@b@  }@b@@b@  public final TFTPPacket receive()@b@    throws IOException, InterruptedIOException, SocketException, TFTPPacketException@b@  {@b@    DatagramPacket packet = new DatagramPacket(new byte[516], 516);@b@@b@    this._socket_.receive(packet);@b@@b@    return TFTPPacket.newTFTPPacket(packet);@b@  }@b@}
<<热门下载>>