• 网络编程day03(UDP中的connect函数、tftp)


    今日任务:tftp的文件上传下载(服务端已经准备好)

    服务端(已上传)

     客户端:

    代码:

    1. #include
    2. #include
    3. #include
    4. #include /* See NOTES */
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. //自定义报错提示
    11. #define ERR_MSG(msg) do{\
    12. fprintf(stderr,"__%d__",__LINE__);\
    13. perror(msg);\
    14. }while(0)
    15. //#define SER_PORT 69
    16. //#define SER_IP "192.168.125.74"
    17. #define SER_PORT 69
    18. #define SER_IP "192.168.125.225"
    19. int do_upload(int cfd,struct sockaddr_in addr);
    20. int do_download(int cfd,struct sockaddr_in addr);
    21. int main(int argc, const char *argv[])
    22. {
    23. //1.创建socket套接字
    24. int cfd=socket(AF_INET,SOCK_DGRAM,0);
    25. if(cfd<0){
    26. ERR_MSG("socket");
    27. return -1;
    28. }
    29. puts("socket success");
    30. //3.接受和发送消息
    31. //目标地址信息
    32. struct sockaddr_in addr;
    33. addr.sin_family=AF_INET;
    34. addr.sin_port=htons(SER_PORT);
    35. addr.sin_addr.s_addr=inet_addr(SER_IP);
    36. socklen_t addrlen=sizeof(addr);
    37. //记录接受信息的目标地址信息
    38. struct sockaddr_in recv_addr;
    39. socklen_t recv_addrlen=sizeof(recv_addr);
    40. while(1){
    41. puts("---------------------------------");
    42. puts("------------1.上传---------------");
    43. puts("------------2.下载---------------");
    44. puts("------------3.退出---------------");
    45. puts("---------------------------------");
    46. puts("请选择>>");
    47. char choice;
    48. choice=getchar();
    49. while(getchar()!='\n');//循环吸收垃圾字符
    50. switch(choice){
    51. case '1':
    52. do_upload(cfd,addr);
    53. break;
    54. case '2':
    55. puts("download");
    56. do_download(cfd,addr);
    57. break;
    58. case '3':
    59. goto END;
    60. }
    61. }
    62. END:
    63. /*
    64. char buf[128];
    65. while(1){
    66. printf("请输入>>>");
    67. fgets(buf,sizeof(buf),stdin);
    68. buf[strlen(buf)-1]='\0';
    69. int send_res=sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&addr,addrlen);
    70. if(send_res<0){
    71. ERR_MSG("sendto");
    72. return -1;
    73. }
    74. puts("sendto success");
    75. if(strcmp(buf,"quit")==0)
    76. break;
    77. bzero(buf,sizeof(buf));
    78. int recv_res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&recv_addr,&recv_addrlen);
    79. if(recv_res<0){
    80. ERR_MSG("recvfrom");
    81. return -1;
    82. }
    83. puts("recvfrom success");
    84. printf("[%s:%d]:%s\n",inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port),buf);
    85. }
    86. */
    87. //4.关闭
    88. close(cfd);
    89. return 0;
    90. }
    91. int do_upload(int cfd,struct sockaddr_in addr){
    92. printf("请输入要上传的文件名.>>>");
    93. char name[20]="";
    94. scanf("%s",name);
    95. while(getchar()!=10);
    96. //组下载协议
    97. char buf[516]="";
    98. //操作码
    99. unsigned short *p1=(unsigned short*)buf;
    100. *p1=htons(2);
    101. //文件名
    102. char *p2=buf+2;
    103. strcpy(p2,name);
    104. //0
    105. //模式
    106. char *p4=p2+strlen(name)+1;
    107. strcpy(p4,"octet");
    108. //0
    109. int size=2+strlen(name)+1+strlen(p4)+1;
    110. //printf("buf==%s;size==%d",buf,size);
    111. //发送协议给服务器
    112. if(sendto(cfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
    113. ERR_MSG("sendto");
    114. return -1;
    115. }
    116. puts("send upload protocal success");
    117. //打开一个文件,输入
    118. int fd=open(name,O_RDONLY);
    119. if(open<0){
    120. ERR_MSG("open");
    121. return -1;
    122. }
    123. unsigned short bNum=1;
    124. //重新定义一个地址的结构体,接受服务端传来的临时地址
    125. struct sockaddr_in dest_addr;
    126. socklen_t addrlen=sizeof(dest_addr);
    127. if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,&addrlen)<0){
    128. ERR_MSG("recvfrom");
    129. return -1;
    130. }
    131. while(1){
    132. //组包:操作码+块编号+数据
    133. bzero(buf,sizeof(buf));
    134. unsigned short *opNum=(unsigned short*)buf;
    135. *opNum=htons(3);
    136. unsigned short *blockNum=opNum+1;
    137. *blockNum=htons(bNum);
    138. char* msg=buf+4;
    139. int read_res=read(fd,msg,512);
    140. if(read<0){
    141. ERR_MSG("read");
    142. }
    143. //发包
    144. ssize_t sendto_res=sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,addrlen);
    145. if(sendto_res<0){
    146. ERR_MSG("sendto");
    147. return -1;
    148. }
    149. printf("sendto_res=%ld\n----",sendto_res);
    150. //接受ack
    151. if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,&addrlen)<0){
    152. ERR_MSG("recvfrom");
    153. return -1;
    154. }
    155. opNum=(unsigned short*)buf;
    156. blockNum=opNum+1;
    157. if(ntohs(*opNum)==5){
    158. puts("操作码错误");
    159. printf("%d %d:%s",ntohs(*opNum),ntohs(*blockNum),msg);
    160. }else if(ntohs(*opNum)==4){
    161. if(ntohs(*blockNum)==bNum){
    162. puts("ACK correct");
    163. }else{
    164. puts("ACK incorrect");
    165. return -1;
    166. }
    167. }
    168. bNum++;
    169. if(read_res<512){
    170. printf("bNUm==%d\n",bNum);
    171. puts("upload done");
    172. break;
    173. }
    174. }
    175. close(fd);
    176. }
    177. int do_download(int cfd,struct sockaddr_in addr){
    178. printf("请输入要下载的文件名.>>>");
    179. char name[20]="";
    180. scanf("%s",name);
    181. while(getchar()!=10);
    182. //组下载协议
    183. char buf[516]="";
    184. //操作码
    185. unsigned short *p1=(unsigned short*)buf;
    186. *p1=htons(1);
    187. //文件名
    188. char *p2=buf+2;
    189. strcpy(p2,name);
    190. //0
    191. //模式
    192. char *p4=p2+strlen(name)+1;
    193. strcpy(p4,"octet");
    194. //0
    195. int size=2+strlen(name)+1+strlen(p4)+1;
    196. //printf("buf==%s;size==%d",buf,size);
    197. //发送协议给服务器
    198. if(sendto(cfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
    199. ERR_MSG("sendto");
    200. return -1;
    201. }
    202. puts("send download protocal success");
    203. //新建打开一个文件,等下写入
    204. int fd=open(name,O_WRONLY|O_CREAT|O_TRUNC,0664);
    205. if(fd<0){
    206. ERR_MSG("open");
    207. return -1;
    208. }
    209. //重新定义一个地址的结构体,接受服务端传来的临时地址
    210. struct sockaddr_in dest_addr;
    211. socklen_t addrlen=sizeof(dest_addr);
    212. while(1){
    213. //接受数据包
    214. int recv_res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,&addrlen);
    215. if(recv_res<0){
    216. ERR_MSG("recvfrom");
    217. return -1;
    218. }
    219. unsigned short* opNum=(unsigned short*)buf;
    220. unsigned short* blockNum=opNum+1;
    221. char * msg=(char *)(blockNum+1);
    222. if(ntohs(*opNum)==5){
    223. puts("操作码错误");
    224. printf("%d %d:%s",ntohs(*opNum),ntohs(*blockNum),msg);
    225. }else if(ntohs(*opNum)==3){
    226. int wr_res=write(fd,msg,recv_res-4);
    227. if(wr_res<0){
    228. ERR_MSG("write");
    229. }else if(wr_res<512){
    230. puts("recvfrom done");
    231. break;
    232. }
    233. }
    234. //组ACK包,吾把buf当做ack来使
    235. *opNum=htons(4);
    236. //回复ACK包
    237. sendto(cfd,buf,4,0,(struct sockaddr*)&dest_addr,addrlen);
    238. bzero(buf,sizeof(buf));
    239. }
    240. //
    241. }

    运行结果:

    不知道是网络的问题还是代码的问题,上传很慢,代码很快正常运行结束了,但是tftp服务端下载到win上很慢,7kb的也要5s以上

    今日思维导图

  • 相关阅读:
    SpringCloud(九)——RabbitMQ简单了解
    C++类与对象(lesson1)
    linux常用库操作命令
    Golang-01Golang开发环境配置
    MySQL 中查看锁
    深度学习实战53-行业描述分类的实战应用:基于ALBERT模型和PyTorch框架的解析
    Python 什么是flask框架?快速入门(flask安装,登录,新手三件套,登录认证装饰器,配置文件,路由系统,CBV)
    多门店座号扫码点餐先付后餐公众号小程序开源版开发
    人工智能论文GPT-3(1):2020.5 Language Models are Few-Shot Learners;摘要;引言;scaling-law
    Android 获取设备内存和外存
  • 原文地址:https://blog.csdn.net/weixin_53762703/article/details/133103289