日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

8.10 网络编程——客户端从服务器中下载文件 TFTP协议

發(fā)布時(shí)間:2023/12/18 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 8.10 网络编程——客户端从服务器中下载文件 TFTP协议 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

利用TFTP協(xié)議 客戶端從服務(wù)器中下載指定文件

過程分析

TFTP通信過程

  • 服務(wù)器在69號端口等待客戶端的請求
  • 服務(wù)器若批準(zhǔn)此請求,則使用 臨時(shí)端口 與客戶端進(jìn)行通信。
  • 每個(gè)數(shù)據(jù)包的編號都有變化(從1開始)
  • 每個(gè)數(shù)據(jù)包都要得到ACK的確認(rèn),如果出現(xiàn)超時(shí),則需要重新發(fā)送最后的數(shù)據(jù)包或ACK包
  • 數(shù)據(jù)長度以512Byte傳輸?shù)?#xff0c;小于512Byte的數(shù)據(jù)意味著數(shù)據(jù)傳輸結(jié)束。
  • 代碼示例

    #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h>//打印錯(cuò)誤新的宏函數(shù) #define ERR_MSG(msg) do{\fprintf(stderr, " __%d__ ", __LINE__);\perror(msg);\ }while(0)int main(int argc, const char *argv[]) {if(argc < 2){fprintf(stderr, "請輸入IP port\n");return -1;}//創(chuàng)建報(bào)式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;}//綁定客戶端自身的地址信息結(jié)構(gòu)體 ---> 非必須綁定 //填充服務(wù)器的IP地址以及端口號 -->因?yàn)榭蛻舳艘鲃?dòng)發(fā)送數(shù)據(jù)包給服務(wù)器struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(69);sin.sin_addr.s_addr = inet_addr(argv[1]);struct sockaddr_in rcv_addrmsg; //存儲接收到的數(shù)據(jù)包來自哪里socklen_t addrlen = sizeof(rcv_addrmsg);//發(fā)送請求char buf[517] = "";bzero(buf, sizeof(buf));char* ptr = buf;short int* pa = (short int*)ptr;*pa = htons(1);char *pb = ptr+2;char filename[128] = "";printf("請輸入要下載的文件名>>>");scanf("%s",filename);getchar();strcpy(pb,filename);char* pd = pb+strlen(filename)+1;strcpy(pd,"octet");int size = 2+strlen(pb)+1+strlen(pd)+1;//將數(shù)據(jù)包發(fā)送給服務(wù)器,所以地址信息結(jié)構(gòu)體需要填服務(wù)器的信息if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0){ERR_MSG("sendto");return -1;}//printf("sendto success\n");//打開文件獲取文件描述符int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);if(fd<0){ERR_MSG("open");return -1;}short int i=0; //定義塊編號while(1){//接收數(shù)據(jù)包bzero(buf,sizeof(buf));ssize_t res;if((res=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&rcv_addrmsg,&addrlen)) < 0){ERR_MSG("recvfrom");return -1;}i++; //塊編號++char *ptr = buf; //數(shù)據(jù)包short int* rpa = (short int*)ptr; //數(shù)據(jù)包操作碼首地址short int* rpb = rpa+1; //數(shù)據(jù)包塊編號首地址char *rpc = ptr+4; //數(shù)據(jù)包數(shù)據(jù)首地址char *errptr = buf; //錯(cuò)誤包short int* epa = (short int*)errptr; //錯(cuò)誤包操作碼地址short int* epb = epa+1; //錯(cuò)誤包的差錯(cuò)碼地址char* epc = (char*)(epb+1); //錯(cuò)誤包差錯(cuò)信息首地址char ACK[5] = ""; //ACKbzero(ACK,sizeof(ACK));short int *acka = (short int*)ACK; //ACK操作碼首地址*acka = htons(4);short int* ackb = acka+1; //ACK塊編號首地址*ackb = htons(i);//判斷是否是數(shù)據(jù)包if(3==ntohs(*rpa)&&i==ntohs(*rpb)){//判斷數(shù)據(jù)包中數(shù)據(jù)大小是否小于512字節(jié)if((res-4)<512){//寫入文件write(fd,rpc,res-4);//發(fā)送ACK驗(yàn)證if(sendto(sfd,ACK,4,0,(struct sockaddr*)&rcv_addrmsg,addrlen)<0){ERR_MSG("sendto");return -1;}//printf("sendto success 結(jié)束\n");break;}else{write(fd,rpc,512);if(sendto(sfd,ACK,4,0,(struct sockaddr*)&rcv_addrmsg,addrlen)<0){ERR_MSG("sendto");return -1;}//printf("sendto success 512 \n");}}elseprintf("ERROR:%s\n",epc); //打印錯(cuò)誤信息}printf("下載成功!\n");//關(guān)閉套接字close(sfd);return 0; }

    測試結(jié)果


    總結(jié)

    以上是生活随笔為你收集整理的8.10 网络编程——客户端从服务器中下载文件 TFTP协议的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。