簡單的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函數在服務器端我用了相對地址,直接用文件名不行(沒有找到原因),還有就是這個服務端接入一個客戶端還好,但是接入多個客戶端就不知道要把信息發給誰(這個問題沒有處理)。
  • 如果后面后時間的話,還想為服務器增添一些登錄驗證的功能,用鏈表存內每個用戶的信息,用戶注冊可以插入鏈表,用戶注銷可以刪掉鏈表,管理員還可以查找用戶信息等等功能,看看現在學習到的東西還很少,還要努力呀!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272197.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272197.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272197.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JavaScript 全局對象

JavaScript 全局對象 全局屬性和函數可用于所有內建的 JavaScript 對象。 頂層函數&#xff08;全局函數&#xff09; 函數描述decodeURI()解碼某個編碼的 URI。decodeURIComponent()解碼一個編碼的 URI 組件。encodeURI()把字符串編碼為 URI。encodeURIComponent()把字符串編碼…

Redis持久化方式~RDB 持久化和AOF 持久化

持久化 Redis 是內存型數據庫&#xff0c;為了保證數據在斷電后不會丟失&#xff0c;需要將內存中的數據持久化到硬盤上。 RDB 持久化 將某個時間點的所有數據都存放到硬盤上。 可以將快照復制到其它服務器從而創建具有相同數據的服務器副本。 如果系統發生故障&#xff0…

Linux文件和目錄權限筆記

查看文件或者目錄的權限命令&#xff1a;ls -al # -a 表示全部文件包含隱藏文件&#xff0c;-l 表示列出每個文件的詳細信息比如執行 ls -altotal 115drwxr--x--- 4 root root 4096 Oct 24 02:07 install.log格式說明&#xff1a;通過 ls -al 格式化輸出的文件詳細信息&#x…

python基礎:序列(列表、元組、字符串)、函數、字典、集合

Python語言運行環境&#xff1a; windowslinuxunixMacos等等 博客記錄內容&#xff1a; Python3的所有語法、面向對象思維、運用模塊進行編程、游戲編程、計算機仿真。 Python是什么類型的語言&#xff1a; Python是腳本語言&#xff0c;腳本語言(Scripting language)是電腦…

Redis 與 Memcached的區別

Redis 與 Memcached 兩者都是非關系型內存鍵值數據庫&#xff0c;主要有以下不同&#xff1a; 數據類型 Memcached 僅支持字符串類型&#xff0c;而 Redis 支持五種不同的數據類型&#xff0c;可以更靈活地解決問題。 數據持久化 Redis 支持兩種持久化策略&#xff1a;RDB…

python基礎(文件、異常、模塊、類、對象)

文件&#xff1a; 打開文件使用open函數&#xff0c;open()的第一個參數是&#xff1a;要打開文件的路徑&#xff0c;如果只傳入文件名那么將在當前文件下查找文件并打開。第二個參數是&#xff1a;文件的打開模式&#xff0c;其他參數都是默認的。文件的打開模式如下圖所示&a…

redis 和 memcached 的區別

redis 和 memcached 的區別 對于 redis 和 memcached 我總結了下面四點。現在公司一般都是用 redis 來實現緩存&#xff0c;而且 redis 自身也越來越強大了&#xff01; redis支持更豐富的數據類型&#xff08;支持更復雜的應用場景&#xff09;&#xff1a;Redis不僅僅支持簡…

樹莓派入門(樹莓派登錄的幾種方式)

什么是嵌入式&#xff1f; 嵌入式即嵌入式系統&#xff0c;IEEE&#xff08;美國電氣和電子工程師協會&#xff09;對其定義是用于控制、監視或者輔助操作機器和設備的裝置&#xff0c;是一種專用的計算機系統。國內普遍認同的嵌入式系統定義是以應用為中心&#xff0c;以計算…

git 如何刪除本地創建的倉庫(轉載自 https://segmentfault.com/q/1010000002996177?_ea=262685)...

可以先清除本地文件夾下的git文件&#xff0c;然后在重新初始化新建的git倉庫 //刪除文件夾下的所有 .git 文件 find . -name ".git" | xargs rm -Rf接著add&#xff0c;commit等操作即可轉載于:https://www.cnblogs.com/xiahl/p/5289266.html

mysql中SQL查詢優化方法總結

1.對查詢進行優化&#xff0c;應盡量避免全表掃描&#xff0c;首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應盡量避免在 where 子句中對字段進行 null 值判斷&#xff0c;否則將導致引擎放棄使用索引而進行全表掃描&#xff0c;如&#xff1a;select id from t w…

Linux庫概念及相關編程(動態庫、靜態庫、環境變量)

分文件編程&#xff1a; 好處&#xff1a;分模塊編程思想&#xff0c;功能和責任劃分清楚便與調試&#xff0c;main函數簡潔&#xff0c;代碼易于閱讀。編程時頭文件有的是使用<>這個符號括起來的&#xff0c;有的是" "使用的是雙引號&#xff0c;使用尖括號括…

復利計算器

import java.util.Scanner;public class Fulijisuan {public static void main(String[] args) {// TODO Auto-generated method stubdouble F0;double singlesum0;double doublesum0;double m0;Scanner scanner new Scanner(System.in);System.out.println("1:復利計算\n…

kali掃描內網ip_Metasploit路由轉發實現內網滲透

利用背景在滲透的過程中常常會遇到這種場景&#xff1a;我們已經通過web滲透拿下一臺內網服務器&#xff0c;為了進一步進行內網滲透&#xff0c;我們會利用“淪陷主機”作為跳板進行進一步的內網滲透&#xff0c;擴大戰果。現在假設的場景是此時我們已經拿下一臺內網服務器的遠…

.NET Core 3.0 中的新變化

譯者&#xff1a;楚人Leo譯文&#xff1a;http://www.cnblogs.com/leolion/p/10585834.html原文&#xff1a;https://msdn.microsoft.com/en-us/magazine/mt848631.aspx.NET Core 3.0 是 .NET Core 平臺的下一主要版本。本文回顧 .NET Core 發展歷史&#xff0c;并展示了它是如…

樹莓派GPIO口的使用(外設相關開發WringPi庫的使用,超聲波、繼電器)

樹莓派的接口&#xff1a; 大而簡單的類別&#xff1a;IO口&#xff0c;input和output是相對于主控芯片來說的&#xff0c;是根據MCU和外設之間的關系將IO口的功能分為output和input。當IO作為input使用時外設有&#xff1a;人體傳感器、煙霧傳感器、火焰傳感器、振動傳感器等…

下拉框+搜索插件

chosen 轉載于:https://www.cnblogs.com/ilikeballs/p/5291983.html

volatile指令重排_有多少人面試栽到Volatile上?面試問題都總結到這兒了

Volatile關鍵字volatile 是Java虛擬機提供的 輕量級 的同步機制.何為 輕量級 呢&#xff0c;這要相對于 synchronized 來說。Volatile有如下三個特點。要搞清楚上面列舉的名詞 可見性 原子性 指令重排 的含義我們需要首先弄清楚JMM(Java內存模型是怎么回事)JMM規定了內存主要劃…

Dubbo核心概念

節點角色規范 節點角色規格Provider提供者公開遠程服務Consumer消費者致電遠程服務Registry注冊表負責服務發現和配置Monitor監視器計算服務調用的數量和耗時Container容器管理服務的生命周期 服務關系 Container負責啟動&#xff0c;加載和運行服務Provider。ProviderRegiste…

良心推薦11款可以稱得上“神器”的Windows工具集合

1、最快文件搜索工具 Everything&#xff1a;當之無愧的最強本地文件搜索神器&#xff0c;搜索任何關鍵詞基本是秒速出現&#xff0c;比Windows自帶的搜索快了太多&#xff0c;電腦文件比較多的人必備&#xff01; 2、專業軟件卸載器 Revo Uninstaller Pro&#xff1a;Windows電…

HDU 2461 Rectangles#容斥原理

http://acm.hdu.edu.cn/showproblem.php?pid2461 題目很簡單&#xff0c;但是由于詢問數M可以很大&#xff0c;所以容易超時&#xff0c;這道題學到了在結構體里面寫函數的方法&#xff0c;這樣子效率更高&#xff0c;否則的話&#xff0c;這道題就TLE了。 根據容斥原理&#…