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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

简单的ftp服务器(客户端、服务器端、socket)

發布時間:2023/12/10 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单的ftp服务器(客户端、服务器端、socket) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

查看本機IP地址:

  • 127.0.0.1

服務器功能:

  • 可以獲取服務器文件使用get指令
  • 可以展示服務器有哪些文件使用ls指令
  • 進入服務器某個文件夾使用指令cd+文件夾名稱
  • 上傳本地文件到服務器,使用指令put
  • pwd可以查看客戶端在當前服務器的位置

客戶端本地功能:

  • lls查看客戶端本地文件
  • lcd+文件名,進入客戶端某個文件
  • lpwd可以查看當前客戶端自己的路徑
  • help可查看服務器支持指令
  • quit退出服務器

寫代碼的時候要寫一個功能編譯驗證一下,不要把所有功能都寫完后再編譯驗證,不容易調試。

簡易FTP服務端代碼:

#include<stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include<stdlib.h> #include<string.h> #include <sys/wait.h> #include <sys/stat.h> #include <fcntl.h>#define LS 0 #define PWD 1#define GET 2 #define PUT 3 #define CD 4 #define HELP 5 #define QUIT 6 #define OUT 7typedef struct Client {char cmd[128];char databuf[1024]; }Cli,*Pcli; char* getcmd(char* cmd) {char* re=NULL;re=strtok(NULL," ");return re; } char* firstcmd(char* cmd) {char*p;p=strtok(cmd," ");return p; } int changmsg(Pcli msg) {char*cmd=firstcmd(msg->cmd);if(strcmp("ls",msg->cmd)==0) return LS;if(strcmp("pwd",msg->cmd)==0) return PWD;if(strcmp("help",msg->cmd)==0) return HELP;if(strcmp("quit",msg->cmd)==0) return QUIT;if(strcmp("get",cmd)==0) return GET;if(strcmp("put",cmd)==0) return PUT;if(strcmp("cd",cmd)==0) return CD; } int receHandle(int fd,Pcli msg) {int ret;int size;int openfd;char* new;char newfilename[128];char* filename;FILE* file;ret=changmsg(msg);switch(ret){case PWD:case LS:file=popen(msg->cmd,"r");memset(msg,'\0',sizeof(Cli));fread(msg->databuf,1,1024,file);write(fd,msg,sizeof(Cli));fclose(file);break;case PUT:filename=getcmd(msg->cmd);openfd=open(filename,O_RDWR|O_CREAT,0660);printf("file has made\n");write(openfd,msg->databuf,strlen(msg->databuf));close(openfd);break;case GET:filename=getcmd(msg->cmd);if(access(filename,F_OK)==0){openfd=open(filename,O_RDWR);size=lseek(openfd,0,SEEK_END);lseek(openfd,0,SEEK_SET);memset(msg->databuf,'\0',1024);read(openfd,msg->databuf,size*sizeof(char));printf("send:%s\n",msg->databuf);write(fd,msg,sizeof(Cli));close(openfd);}else{memset(msg->cmd,'\0',128);strcpy(msg->cmd,"no");write(fd,msg,sizeof(Cli));}break;case CD:filename=getcmd(msg->cmd);sprintf(newfilename,"./%s",filename);if(access(newfilename,F_OK)==0){memset(msg->cmd,'\0',128);strcpy(msg->cmd,"yes");write(fd,msg,sizeof(Cli));chdir(newfilename);}else{memset(msg->cmd,'\0',128);strcpy(msg->cmd,"no");write(fd,msg,sizeof(Cli));}break;case HELP:memset(msg,'\0',sizeof(Cli));strcpy(msg->databuf,"cd\nlcd\nls\nlls\npwd\nlpwd\nput\nget\nhelp");write(fd,msg,sizeof(Cli));break;case QUIT:close(fd);return OUT;break;} }int main() {int bindre;int newfd;int re;int socketre;int listenre;pid_t fpid;Cli msg;struct sockaddr_in IP;struct sockaddr_in CLI;//客戶端信息int len=sizeof(struct sockaddr_in);memset(&IP,'\0',len);memset(&CLI,'\0',len);IP.sin_family=AF_INET;IP.sin_port=htons(8686);IP.sin_addr.s_addr=inet_addr("192.168.1.198");socketre=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(socketre==-1){printf("create fail\n");perror("socket");exit(-1);}bindre=bind(socketre,(struct sockaddr*)&IP,len);if(bindre==-1){perror("bind");printf("bind fail\n");exit(-1);}listenre=listen(socketre,10);if(listenre==-1){printf("listen fail\n");perror("listen");exit(-1);}while(1){newfd=accept(socketre,(struct sockaddr*)&CLI,&len);if(newfd==-1){perror("accept");printf("accept fail\n");exit(-1);}printf("get client:%s\n",inet_ntoa(CLI.sin_addr));fpid=fork();if(fpid==0){while(1){memset(&msg,'\0',sizeof(Cli));if(read(newfd,&msg,sizeof(Cli))!=0){re=receHandle(newfd,&msg);if(re==OUT){printf("client is quit!\n");break;}}else {printf("Error! Don't connect!\n");break;}}}if(fpid>0){waitpid(fpid,NULL,WNOHANG | WUNTRACED);}}return 0; }

服務端代碼:

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/stat.h> #include <fcntl.h> #include <signal.h> #define LS 0 #define PWD 1 #define GET 2 #define PUT 3 #define CD 4 #define HELP 5 #define NO 6 #define LCD 7 #define LLS 8 #define LPWD 9 #define QUIT 10 #define OUT 11 typedef struct Client {char cmd[128];char databuf[1024]; }Cli,*Pcli; char* getcmd(char* cmd) {char* p;p=strtok(cmd," ");return p; } int changmsg(Pcli snd) {char* cmd=firstcmd(snd->cmd);if(strcmp("lls",snd->cmd)==0) return LLS;if(strcmp("quit",snd->cmd)==0) return QUIT;if(strcmp("ls",snd->cmd)==0) return LS;if(strcmp("pwd",snd->cmd)==0) return PWD;if(strcmp("quit",snd->cmd)==0) return QUIT;if(strcmp("lpwd",snd->cmd)==0) return LPWD;if(strcmp("help",snd->cmd)==0) return HELP;if(strcmp(cmd,"get")==0) return GET;if(strcmp(cmd,"put")==0) return PUT;if(strcmp(cmd,"cd")==0) return CD;if(strcmp(cmd,"lcd")==0) return LCD;return NO; } int client_Handle(int fd,Pcli snd) {int ret;int openfd;int size;char newcmd[128];char* filename;strcpy(newcmd,snd->cmd);ret=changmsg(snd);switch(ret){case LLS:printf("---------------------------------------------------------");putchar('\n');system("ls");putchar('\n');printf("---------------------------------------------------------\n");break;case LPWD:printf("---------------------------------------------------------");putchar('\n');system("pwd");putchar('\n');printf("---------------------------------------------------------\n");break;case PWD:case LS:case HELP:write(fd,snd,sizeof(Cli));read(fd,snd,sizeof(Cli));printf("---------------------------------------------------------");putchar('\n');printf("%s",snd->databuf);putchar('\n');printf("---------------------------------------------------------\n");memset(snd,'\0',sizeof(Cli));break;case PUT:filename=getcmd(snd->cmd);if(access(filename,F_OK)==0){openfd=open(filename,O_RDWR);size=lseek(openfd,0,SEEK_END);lseek(openfd,0,SEEK_SET);memset(snd->databuf,'\0',1024);read(openfd,snd->databuf,sizeof(char)*size);memset(snd->cmd,'\0',128);strcpy(snd->cmd,newcmd);write(fd,snd,sizeof(Cli));close(openfd);}else{printf("文件不存在\n");}break;case GET:filename=getcmd(snd->cmd);strcpy(snd->cmd,newcmd);write(fd,snd,sizeof(Cli));memset(snd->databuf,'\0',1024);read(fd,snd,sizeof(Cli));if(strcmp(snd->cmd,"no")==0){printf("No This File!\n");}else{openfd=open(filename,O_RDWR|O_CREAT,0660);write(openfd,snd->databuf,strlen(snd->databuf));close(openfd);}break;case CD:memset(snd->cmd,'\0',128);strcpy(snd->cmd,newcmd);write(fd,snd,sizeof(Cli));memset(snd->cmd,'\0',128);read(fd,snd,sizeof(Cli));if(strcmp(snd->cmd,"no")==0){printf("File isn't exist!\n");}else{printf("get:%s\n",snd->cmd);}break;case LCD:filename=getcmd(snd->cmd);if(access(filename,F_OK)==0){chdir(filename);}else{printf("Under the path,dont't have this file!\n");}break;case NO:printf("command isn't exist.\n");break;case QUIT:strcpy(snd->cmd,"quit");write(fd,snd,sizeof(Cli));close(fd);return OUT;break;} } int main() {int socketfd;int conre;int handre;char cmd[128];char*writebuf;char*readbuf;char mark[128];Cli sendmsgr;struct Client CL;struct sockaddr_in addr;addr.sin_family=AF_INET;addr.sin_port=htons(8686);addr.sin_addr.s_addr=inet_addr("192.168.1.198");socketfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(socketfd==-1){printf("socket create fail\n");perror("socket");exit(-1);}conre=connect(socketfd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in));if(conre==-1){printf("connect fail\n");perror("connect");exit(-1);}printf("hanve conected server...\n");while(1){memset(&sendmsgr,'\0',sizeof(Cli));printf(">");fgets(cmd,128,stdin);strncpy(sendmsgr.cmd,cmd,strlen(cmd)-1);printf("cmd:%s\n",sendmsgr.cmd);handre=client_Handle(socketfd,&sendmsgr);if(handre==OUT){printf("server is quit!\n");exit(0);}}return 0; }

學習體會補充:

  • read是有返回值n的,如果n>0,那么就可以讀到BUF里去,n=0,說明客戶端發送了FIN信號,就斷開連接,n<0,說明發生了中斷或者錯誤。
  • 學習到新的函數chdir和access的用法,更加深入的了解socket網絡編程函數的使用,鞏固了之前文件系統那里學習到的函數,對結構體和指針的使用更加熟練,總的來說,代碼不難但是第一次那么長的代碼,還是有點小難度的,只要注意客戶端和服務端傳遞參數的時候要保證發送和接收的類型一樣就好,這里我就用了結構體來存放發送的信息,那么接收也要用結構體,注意初始化,還有就是write的時候最好有多少東西就寫多少東西不然內容后面會有很多亂碼,chdir函數在服務器端我用了相對地址,直接用文件名不行(沒有找到原因),還有就是這個服務端接入一個客戶端還好,但是接入多個客戶端就不知道要把信息發給誰(這個問題沒有處理)。
  • 如果后面后時間的話,還想為服務器增添一些登錄驗證的功能,用鏈表存內每個用戶的信息,用戶注冊可以插入鏈表,用戶注銷可以刪掉鏈表,管理員還可以查找用戶信息等等功能,看看現在學習到的東西還很少,還要努力呀!!

總結

以上是生活随笔為你收集整理的简单的ftp服务器(客户端、服务器端、socket)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。