当前位置:   article > 正文

坐牢第二十六天(tftp文件传输)

坐牢第二十六天(tftp文件传输)

1.基于UDP的TFTP文件传输

1)tftp协议概述

简单文件传输协议,适用于在网络上进行文件传输的一套标准协议,使用UDP传输

特点:

是应用层协议

基于UDP协议实现

数据传输模式

octet:二进制模式(常用)

mail:已经不再支持

2)tftp下载模型

TFTP通信过程总结

服务器在69号端口等待客户端的请求

服务器若批准此请求,则使用 临时端口 与客户端进行通信。

每个数据包的编号都有变化(从1开始)

每个数据包都要得到ACK的确认,如果出现超时,则需要重新发送最后的数据包或ACK包

数据长度以512Byte传输的,小于512Byte的数据意味着数据传输结束。

3)tftp协议分析

 4)代码

main.c

  1. #include "tftp.h"
  2. int main(int argc, char const *argv[])
  3. {
  4. while (1)
  5. {
  6. // 菜单
  7. printf("*******************\n");
  8. printf("******1:下载*******\n");
  9. printf("******2:上传*******\n");
  10. printf("******0:退出*******\n");
  11. printf("*******************\n");
  12. int a = -1;
  13. printf("请输入要进行的功能:");
  14. scanf("%d", &a);
  15. switch (a)
  16. {
  17. case 1:
  18. {
  19. // 调用下载函数
  20. if (download() == -1)
  21. {
  22. perror("下载失败");
  23. return -1;
  24. }
  25. printf("请输入任意字符后按回车键继续...");
  26. getchar(); // 等待用户输入一个字符
  27. system("clear"); // 清空终端(在Linux系统中)
  28. }
  29. break;
  30. case 2:
  31. {
  32. // 调用上传函数
  33. if (upload() == -1)
  34. {
  35. perror("上传失败");
  36. return -1;
  37. }
  38. printf("请输入任意字符后按回车键继续...");
  39. getchar(); // 等待用户输入一个字符
  40. system("clear"); // 清空终端(在Linux系统中)
  41. }
  42. break;
  43. case 0:
  44. {
  45. goto END;
  46. }
  47. break;
  48. default:
  49. printf("请重新输入\n");
  50. break;
  51. }
  52. }
  53. END:
  54. return 0;
  55. }

 tfitp.c

  1. #include "tftp.h"
  2. //定义下载文件函数
  3. int download()
  4. {
  5. // 创建套接字文件
  6. int cfd = socket(AF_INET, SOCK_DGRAM, 0);
  7. if (cfd == -1)
  8. {
  9. perror("socket error");
  10. return -1;
  11. }
  12. //printf("cfd = %d\n", cfd); // 3
  13. // 向服务器发送下载请求
  14. char buf[516] = "";
  15. short *p1 = (short *)buf; // 操作码
  16. *p1 = htons(1);
  17. char *p2 = buf + 2; // 文件名
  18. printf("请输入要下载的文件名:");
  19. scanf("%s", p2);
  20. getchar();
  21. char *p4 = p2 + strlen(p2) + 1;
  22. strcpy(p4, "octet");
  23. int size = 2 + strlen(p2) + strlen(p4) + 2; // 请求包总长度
  24. // 将请求包发送给服务器
  25. struct sockaddr_in sin;
  26. sin.sin_family = AF_INET;
  27. sin.sin_port = htons(SER_PORT);
  28. sin.sin_addr.s_addr = inet_addr(SER_IP);
  29. sendto(cfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin));
  30. printf("请求包发送成功\n");
  31. // 绑定客户端
  32. struct sockaddr_in cin;
  33. cin.sin_family = AF_INET;
  34. cin.sin_port = htons(CLI_PORT);
  35. cin.sin_addr.s_addr = inet_addr(CLI_IP);
  36. // 打开要写入的文件
  37. int fd = -1;
  38. if ((fd = open(p2, O_WRONLY | O_CREAT | O_TRUNC, 0664)) == -1)
  39. {
  40. perror("open error");
  41. return -1;
  42. }
  43. // 接收数据包
  44. char msg[516] = "";
  45. socklen_t len = sizeof(sin);
  46. while (1)
  47. {
  48. int n = recvfrom(cfd, msg, sizeof(msg), 0, (struct sockaddr *)&sin, &len);
  49. printf("%d\n",n);
  50. if (n==-1)
  51. {
  52. perror("recvfrom error");
  53. return -1;
  54. }
  55. short *p5 = (short *)msg; // 操作码
  56. short *p6 = (short *)(msg + 2); // 块编号
  57. char *p7 = msg + 4; // 文件内容
  58. short num = ntohs(*p5);
  59. short key = ntohs(*p6);
  60. if (num == 3)
  61. {
  62. // 处理数据包
  63. write(fd, p7, n-4);
  64. // 发送ACK
  65. char ack[516] = "";
  66. short *p8 = (short *)ack; // 操作码
  67. *p8 = htons(4);
  68. short *p9 = (short *)(ack + 2); // 块编号
  69. *p9 = htons(key);
  70. sendto(cfd, ack, 4, 0, (struct sockaddr *)&sin, sizeof(sin));
  71. if (n< 516)
  72. {
  73. printf("文件下载完毕\n");
  74. break;
  75. }
  76. }
  77. else if (num == 5)
  78. {
  79. printf("error\n");
  80. break;
  81. }
  82. }
  83. // 关闭文件描述符
  84. close(cfd);
  85. close(fd);
  86. }
  87. //定义上传文件函数
  88. int upload()
  89. {
  90. // 创建套接字文件
  91. int cfd = socket(AF_INET, SOCK_DGRAM, 0);
  92. if (cfd == -1)
  93. {
  94. perror("socket error");
  95. return -1;
  96. }
  97. printf("cfd = %d\n", cfd); // 3
  98. // 向服务器发送上传请求
  99. char buf[516] = "";
  100. short *p1 = (short *)buf; // 操作码
  101. *p1 = htons(2);
  102. char *p2 = buf + 2; // 文件名
  103. printf("请输入要上传的文件名:");
  104. scanf("%s", p2);
  105. getchar();
  106. char *p4 = p2 + strlen(p2) + 1;
  107. strcpy(p4, "octet");
  108. int size = 2 + strlen(p2) + strlen(p4) + 2; // 请求包总长度
  109. // 将请求包发送给服务器
  110. struct sockaddr_in sin;
  111. sin.sin_family = AF_INET;
  112. sin.sin_port = htons(SER_PORT);
  113. sin.sin_addr.s_addr = inet_addr(SER_IP);
  114. socklen_t len = sizeof(sin);//数据包大小
  115. sendto(cfd, buf, size, 0, (struct sockaddr *)&sin, len);
  116. printf("请求包发送成功\n");
  117. // 绑定客户端
  118. struct sockaddr_in cin;
  119. cin.sin_family = AF_INET;
  120. cin.sin_port = htons(CLI_PORT);
  121. cin.sin_addr.s_addr = inet_addr(CLI_IP);
  122. // 打开要上传的文件
  123. int fd = -1;
  124. if ((fd = open(p2, O_RDONLY)) == -1)
  125. {
  126. perror("open error");
  127. return -1;
  128. }
  129. short n = 0;
  130. while (1)
  131. {
  132. // 等待ACK
  133. if (recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr *)&sin, &len) == -1)
  134. {
  135. perror("接收ACK失败");
  136. close(fd);
  137. return -1;
  138. }
  139. // 准备一个要发送的数据包
  140. char msg[516] = "";
  141. short *p5 = (short *)msg; // 操作码
  142. *p5 = htons(3);
  143. short *p6 = (short *)(msg + 2); // 块编号
  144. *p6 = htons(++n);
  145. char *p7 = msg + 4; // 文件内容
  146. read(fd, p7, 512);
  147. int size_msg = 4 + strlen(p7);
  148. // 发送数据包
  149. sendto(cfd, msg, size_msg, 0, (struct sockaddr *)&sin, len);
  150. printf("发送成功\n");
  151. // 接收ACK
  152. char ack[516] = "";
  153. short *p8 = (short *)ack; // 操作码
  154. short *p9 = (short *)(ack + 2); // 块编号
  155. recvfrom(cfd, ack, 4, 0, (struct sockaddr *)&sin, &len);
  156. // 判断是否上传完毕
  157. if (strlen(p7) < 512)
  158. {
  159. printf("文件上传完毕\n");
  160. break;
  161. }
  162. }
  163. close(cfd);
  164. close(fd);
  165. return 0;
  166. }

 

tftp.h

  1. #ifndef TFTP_H
  2. #define TFTP_H
  3. #define SER_PORT 69 // 服务器端口号
  4. #define SER_IP "192.168.0.131" // 服务器ip地址
  5. #define CLI_PORT 5555 // 客户端端口号
  6. #define CLI_IP "192.168.0.105" // 客户端地址
  7. #include<myhead.h>
  8. //定义下载文件函数
  9. int download();
  10. //定义上传文件函数
  11. int upload();
  12. #endif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/998724
推荐阅读
相关标签
  

闽ICP备14008679号