基於TCP的TFTP(Trivial File Transfer Protocol,簡單檔案傳輸通訊協定) 的c編程實現

來源:互聯網
上載者:User

標籤:tcp   tftp   網路編程   linux   進程   

我們或許都聽到過,TFTP(Trivial File Transfer Protocol,簡單檔案傳輸通訊協定)是TCP/IP協議族中的一個用來在客戶機與伺服器之間進行簡單檔案傳輸的協議,提供不複雜、開銷不大的檔案傳輸服務。

本文就簡單的敘述下tftp的小檔案傳輸功能以及用戶端對伺服器的列表功能。

之前就一直很納悶,我們經常在網上下載什麼東西或者從別處傳輸一個檔案,具體是怎麼實現的呢?於是乎,翻查一些資料,加上自己對網路編程的逐步加深,所以功夫不負有心人,還算是大致的完成了下。

本常式實現的功能呢? 就是實現用戶端對伺服器端提供的檔案上傳與下載功能,還有對伺服器端目錄的顯示功能,好了,請閱讀下面的編程實現部分:


首先是伺服器端:



#include<head.h>typedef struct {int type;int size;char mtxt[1024];}MSG;#define PUT_FILE   10 #define GET_FILE   20 #define LIST_DIR   30 #define NEXIST_FILE 40 #define YEXIST_FILE 50void handler_signal(int signum){waitpid(-1,NULL,WNOHANG);printf("CHild process over!\n");}void do_put(int sockfd,MSG *pmsg){int fd;fd = open(pmsg->mtxt,O_WRONLY | O_CREAT | O_TRUNC,0666);if(fd < 0){fprintf(stderr,"Fail to open %s : %s\n",pmsg->mtxt,strerror(errno));exit(EXIT_FAILURE);}if(ftruncate(fd,pmsg->size) < 0){perror("Fail to ftruncate");exit(EXIT_FAILURE);}while(1){if(recv(sockfd,pmsg,sizeof(MSG),0) <= 0)break;if(pmsg->size == 0)break;write(fd,pmsg->mtxt,pmsg->size);}return ;}int do_get(int sockfd,MSG *pmsg){int fd;struct stat f_info;fd = open(pmsg->mtxt,O_RDONLY);if(fd < 0){fprintf(stderr,"Fail to open %s : %s\n",pmsg->mtxt,strerror(errno));pmsg->type = NEXIST_FILE;}if(fstat(fd,&f_info) < 0){perror("Fail to fstat");pmsg->type = NEXIST_FILE;}if(pmsg->type == NEXIST_FILE){//告訴用戶端結果send(sockfd,pmsg,sizeof(MSG),0);return -1;}else{pmsg->type = YEXIST_FILE;pmsg->size = f_info.st_size;send(sockfd,pmsg,sizeof(MSG),0);}while(1){pmsg->size = read(fd,pmsg->mtxt,sizeof(pmsg->mtxt));if(send(sockfd,pmsg,sizeof(MSG),0) < 0){perror("Fail to send");exit(EXIT_FAILURE);}if(pmsg->size == 0)break;}return 0;}int do_list(int sockfd){DIR *pdir;MSG msg;struct dirent *pdirent;pdir = opendir(".");if(pdir == NULL){msg.type = NEXIST_FILE;send(sockfd,&msg,sizeof(MSG),0);return -1;}while ( pdirent = readdir(pdir) ){if(pdirent->d_name[0] == '.')continue;msg.type = YEXIST_FILE;strcpy(msg.mtxt,pdirent->d_name);if(send(sockfd,&msg,sizeof(MSG),0) < 0){perror("Fail to send");exit(EXIT_FAILURE);}}msg.type = NEXIST_FILE;if(send(sockfd,&msg,sizeof(MSG),0) < 0){perror("Fail to send");exit(EXIT_FAILURE);}return 0;}void do_client(int connect_fd){MSG msg;while(1){if(recv(connect_fd,&msg,sizeof(MSG),0) <= 0){perror("Fail to recv");exit(EXIT_FAILURE);}switch(msg.type){case PUT_FILE:do_put(connect_fd,&msg);break;case GET_FILE:do_get(connect_fd,&msg);break;case LIST_DIR:do_list(connect_fd);break;}}exit(EXIT_SUCCESS);}int main(int argc, const char *argv[]){int listen_fd;pid_t pid;int connect_fd;struct sockaddr_in server_addr;struct sockaddr_in peer_addr;socklen_t addrlen = sizeof(struct sockaddr_in);if(argc < 3){fprintf(stderr,"Usage : %s ip port\n",argv[0]);exit(EXIT_FAILURE);}if(signal(SIGCHLD,handler_signal) == SIG_ERR){perror("Fail to signal");exit(EXIT_FAILURE);}listen_fd = socket(AF_INET,SOCK_STREAM,0);if(listen_fd < 0){perror("Fail to socket");exit(EXIT_FAILURE);}server_addr.sin_family = AF_INET;server_addr.sin_port   = htons(atoi(argv[2]));server_addr.sin_addr.s_addr = inet_addr(argv[1]);if(bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr_in)) < 0){perror("Fail to bind");exit(EXIT_FAILURE);}listen(listen_fd,128);printf("listen ...\n");while(1){connect_fd = accept(listen_fd,(struct sockaddr *)&peer_addr,&addrlen);if(connect_fd < 0){perror("Fail to accept");exit(EXIT_FAILURE);}printf("------------------------------------------------\n");printf("connect_fd = %d\n",connect_fd);printf("Port : %d\n",ntohs(peer_addr.sin_port));printf("IP   : %s\n",inet_ntoa(peer_addr.sin_addr));printf("---------------------------------------------\n");pid = fork();if(pid < 0){perror("Fail to fork");exit(EXIT_FAILURE);}if(pid == 0){close(listen_fd);do_client(connect_fd);}//避免檔案描述符號浪費close(connect_fd);}return 0;}

再來看用戶端:


#include <head.h>typedef struct {int type;int size;char mtxt[1024];}MSG;#define PUT_FILE 10 #define GET_FILE 20 #define LIST_DIR 30 #define NEXIST_FILE 40 #define YEXIST_FILE 50int do_put(int sockfd,char *filename){int fd;MSG msg;struct stat f_info;fd = open(filename,O_RDONLY);if(fd < 0){fprintf(stderr,"Fail to open %s : %s\n",filename,strerror(errno));return -1;}if(fstat(fd,&f_info) < 0){perror("Fail to fstat");return -1;}msg.type = PUT_FILE;msg.size = f_info.st_size;strcpy(msg.mtxt,filename);if(send(sockfd,&msg,sizeof(MSG),0) < 0){perror("Fail to send");exit(EXIT_FAILURE);}while(1){msg.size = read(fd,msg.mtxt,sizeof(msg.mtxt));if(send(sockfd,&msg,sizeof(MSG),0) < 0){perror("Fail to send");exit(EXIT_FAILURE);}if(msg.size == 0)break;}return 0;}int do_get(int sockfd,char *filename){int fd;MSG msg;msg.type = GET_FILE;strcpy(msg.mtxt,filename);if(send(sockfd,&msg,sizeof(MSG),0) < 0){perror("Fail to send");exit(EXIT_FAILURE);}//等待伺服器端結果:檔案存放或不存在if(recv(sockfd,&msg,sizeof(MSG),0) <= 0){perror("Fail to send");exit(EXIT_FAILURE);}if(msg.type == NEXIST_FILE){printf("The get file:%s is not exist!\n",filename);return -1;}fd = open(msg.mtxt,O_WRONLY | O_CREAT | O_TRUNC,0666);if(fd < 0){fprintf(stderr,"Fail to open %s : %s\n",msg.mtxt,strerror(errno));exit(EXIT_FAILURE);}if(ftruncate(fd,msg.size) < 0){perror("Fail to ftruncate");exit(EXIT_FAILURE);}while(1){if(recv(sockfd,&msg,sizeof(MSG),0) <= 0)break;if(msg.size == 0)break;write(fd,msg.mtxt,msg.size);}return 0;}int do_list(int sockfd){MSG msg;msg.type = LIST_DIR;if(send(sockfd,&msg,sizeof(MSG),0) < 0){perror("Fail to send");exit(EXIT_FAILURE);}while(1){if(recv(sockfd,&msg,sizeof(MSG),0) <= 0)break; if(msg.type == NEXIST_FILE)break;printf("%s\n",msg.mtxt);}return 0;}int do_task(int sockfd,char *pcmd,char *filename){if(strncmp(pcmd,"get",3) == 0){do_get(sockfd,filename);}else if(strncmp(pcmd,"put",3) == 0){do_put(sockfd,filename);}else if(strncmp(pcmd,"list",4) == 0){do_list(sockfd);}else{printf("Invalid cmd : %s\n",pcmd);return -1;}return 0;}int main(int argc, const char *argv[]){char buf[1024];int sockfd;char *pcmd,*pname;int connect_fd;struct sockaddr_in server_addr;if(argc < 3){fprintf(stderr,"Usage : %s ip port\n",argv[0]);exit(EXIT_FAILURE);}sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd < 0){perror("Fail to socket");exit(EXIT_FAILURE);}server_addr.sin_family = AF_INET;server_addr.sin_port   = htons(atoi(argv[2]));server_addr.sin_addr.s_addr = inet_addr(argv[1]);if(connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr_in)) < 0){perror("Fail to bind");exit(EXIT_FAILURE);}while(1){printf(">");fgets(buf,sizeof(buf),stdin);buf[strlen(buf) - 1] = '\0';if(strncmp(buf,"quit",4) == 0)break;pcmd  = strtok(buf," ");pname = strtok(NULL," ");do_task(sockfd,pcmd,pname);}return 0;}

或許生活就是這個樣子,當你想要去做一件事情的時候,那就認真的去做吧,肯定會成功的,或許我們的現在看起來是多麼的狼狽不堪,但是我們都沒有嘲笑別人的權利,因為成功的人畢竟是少數,我們不能以常人的思維去判斷一個人的價值取向,如果真的想實現我們的夢想,那麼此時此刻,就是我們應該認真做事,好好做人的時候了,我堅信當你的事業到達一個程度的時候,你的人格魅力將會自動的提升上去。

O(∩_∩)O~於君共勉


基於TCP的TFTP(Trivial File Transfer Protocol,簡單檔案傳輸通訊協定) 的c編程實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.