简单的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.mzph.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了。 根据容斥原理&#…