TFTP管理软件
ciscotftpserver.rar

测试代码
TFTP.zip

TFTP

TFTP是一个传输文件的简单协议,它基于UDP协议而实现,但是我们也不能确定有些TFTP协议是基于其它传输协议完成的。此协议设计的时候是进行小文件传输的。因此它不具备通常的FTP的许多功能,它只能从文件服务器上获得或写入文件,不能列出目录,不进行认证,它传输8位数据。传输中有三种模式:netascii,这是8位的ASCII码形式,另一种是octet,这是8位源数据类型;最后一种mail已经不再支持,它将返回的数据直接返回给用户而不是保存为文件。

优点:

1、TFTP可用于UDP环境;比如当需要将程序或者文件同时向许多机器下载时就往往需要使用到TFTP协议。

2、TFTP代码所占的内存较小,这对于较小的计算机或者某些特殊用途的设备来说是很重要的(比如我们一些简单的Linux嵌入式设备),这些设备不需要硬盘,只需要固化了TFTP、UDP和IP的小容量只读存储器即可。

3、不需要验证客户端的权限,在局域网中调试设备时传输文件就减少了很多步骤。

缺点:

TFTP是一个传输文件的简单协议,此协议设计的时候是进行小文件传输的。因此它不具备通常的FTP的许多功能,它只能从文件服务器上获得或写入文件,不能列出目录。

总结

在一些嵌入式局域网的软件调试过程中,我们可以用TFTP来传输我们调试过程中产生的文件,如一些临时验证的可执行文件,抓包文件,TFTP搭建传输环境简单,可以提高我们的调试效率。但是如果是一些比较大的文件并且是互联网传输的,小编我还是建议大家用FTP。

环境配置

首先需要在Windows支持上开启TFTP服务,

image.png
其次需要下载tftp服务端软件,这点与ftp不同,tftp需要额外下载管理软件,我这边下载的是Cisco TFTP。当然用自己的代码也可以实现,但是显然已有的软件更加成熟

image.pngimage.pngimage.png

上传与下载代码

需要先导进去meaven依赖

  1. <dependency>
  2. <groupId>commons-net</groupId>
  3. <artifactId>commons-net</artifactId>
  4. <version>3.3</version>
  5. </dependency>
  1. package com.example.demo;
  2. import org.apache.commons.net.tftp.TFTP;
  3. import org.apache.commons.net.tftp.TFTPClient;
  4. import java.io.*;
  5. import java.net.SocketException;
  6. import java.net.UnknownHostException;
  7. public class TFTPUtil {
  8. private static TFTPClient tftp = new TFTPClient();
  9. public static boolean downloadFile(String hostname, String localFilename,
  10. String remoteFilename,int port) {
  11. // 设置超时时间为60秒
  12. tftp.setDefaultTimeout(60000);
  13. // 打开本地socket
  14. try {
  15. tftp.open();
  16. } catch (SocketException e) {
  17. System.out.println("无法打开本地 UDP socket!");
  18. System.out.println(e.getMessage());
  19. }
  20. boolean closed,success;
  21. closed = false;
  22. success = false;
  23. FileOutputStream output = null;
  24. File file;
  25. file = new File(localFilename);
  26. if (file.exists()) {
  27. System.out.println("文件: " + localFilename + " 已经存在!");
  28. return success;
  29. }
  30. try {
  31. output = new FileOutputStream(file);
  32. } catch (IOException e) {
  33. tftp.close();
  34. System.out.println("无法打开要写入的本地文件!");
  35. System.out.println(e.getMessage());
  36. return success;
  37. }
  38. try {
  39. // tftp.receiveFile(remoteFilename, TFTP.BINARY_MODE, output, hostname, port);
  40. tftp.receiveFile(remoteFilename, TFTP.BINARY_MODE, output, hostname);
  41. System.out.println(1);
  42. success = true;
  43. }
  44. // catch (UnknownHostException e) {
  45. // System.out.println("无法解析主机!");
  46. // System.out.println(e.getMessage());
  47. // return success;
  48. // } catch (IOException e) {
  49. // System.out.println("接收文件时有I/O异常!");
  50. // System.out.println(e.getMessage());
  51. // return success;
  52. // }
  53. catch (Exception e){
  54. System.out.println("发生错误");
  55. System.out.println(e.getMessage());
  56. }
  57. finally {
  58. // 关闭本地 socket 和输出的文件
  59. tftp.close();
  60. try {
  61. if (null != output) {
  62. output.close();
  63. }
  64. closed = true;
  65. } catch (IOException e) {
  66. closed = false;
  67. System.out.println("关闭文件时出错!");
  68. System.out.println(e.getMessage());
  69. }
  70. }
  71. if (!closed)
  72. return false;
  73. return success;
  74. }
  75. public static boolean uploadFile(String hostname, String remoteFilename, InputStream input , int port) {
  76. // 设置超时时间为10秒
  77. tftp.setDefaultTimeout(10000);
  78. // 打开本地socket
  79. try {
  80. tftp.open();
  81. } catch (SocketException e) {
  82. System.out.println("无法打开本地 UDP socket!");
  83. System.out.println(e.getMessage());
  84. }
  85. boolean success,closed;
  86. closed = false;
  87. success = false;
  88. try {
  89. tftp.sendFile(remoteFilename, TFTP.BINARY_MODE, input, hostname, port);
  90. success = true;
  91. } catch (UnknownHostException e) {
  92. System.out.println("无法解析主机!");
  93. System.out.println(e.getMessage());
  94. return success;
  95. } catch (IOException e) {
  96. System.out.println("发送文件时有I/O异常!");
  97. System.out.println(e.getMessage());
  98. return success;
  99. //System.exit(1);
  100. } finally {
  101. // 关闭本地 socket 和输出的文件
  102. tftp.close();
  103. try {
  104. if (null != input) {
  105. input.close();
  106. }
  107. closed = true;
  108. } catch (IOException e) {
  109. closed = false;
  110. System.out.println("关闭文件时出错!");
  111. System.out.println(e.getMessage());
  112. }
  113. }
  114. if (!closed)
  115. return false;
  116. return success;
  117. }
  118. public static boolean uploadFile(String hostname, String remoteFilename, String localFilePath,int port) {
  119. FileInputStream fileInput=null;
  120. try {
  121. fileInput=new FileInputStream(localFilePath);
  122. } catch (FileNotFoundException e) {
  123. e.printStackTrace();
  124. }
  125. return uploadFile( hostname, remoteFilename, fileInput , port);
  126. }
  127. public static void main(String[] args) {
  128. String hostname="127.0.0.1";
  129. String remoteFilename="/Log.txt";
  130. String localFilePath="D:/1.txt";
  131. int port=69;
  132. TFTPUtil.uploadFile(hostname, remoteFilename, localFilePath, port);
  133. TFTPUtil.downloadFile("localhost", "D:/44.txt", "/txt.txt", 69);
  134. }
  135. }

实验与结论

当我打开程序,准备体验来自UDP速度,结果让人大跌眼镜,在本地速度居然只有不到200kB,赶紧上网百度了下,发现TFTP本身速度就是很慢

image.png

原因总结如下:

tftp是基于UDP的,ftp是基于tcp的,但是tftp的传输速度远不及tfp。tftp采用的是简单的停止等待协议,发出去的UDP包必须要等待对方的回答或者超时才能开始下一个UDP发送或者重传。而FTP只要对方有ACK表示有win空间就可以持续的发,所以FTP要比TFTP快很多。