Llinux微型文件传输要点.docx
- 文档编号:10407750
- 上传时间:2023-02-11
- 格式:DOCX
- 页数:39
- 大小:42.82KB
Llinux微型文件传输要点.docx
《Llinux微型文件传输要点.docx》由会员分享,可在线阅读,更多相关《Llinux微型文件传输要点.docx(39页珍藏版)》请在冰豆网上搜索。
Llinux微型文件传输要点
局域网文件传输系统项目说明
需求说明:
1,开发平台
1.1linuxx8664
1.2支持DebianUbuntu
1.3支持rhel,centos,Fedora
2,功能说明
1.1文件上传与下载,讲指定文件上传到服务器,抑从服务器下载文件到指定位置
1.2文件浏览,浏览本地文件以及服务器端文件
1.3概要
功能说明
1.3.1客户端
主要任务:
1)分析用户输入的命令
2)根据命令向服务器端发出请求
3)等待服务器返回的结果
表1_1命令含义与请求码
用户输入的命令
命令含义
对应的请求码
Get
从服务器得到文件
GET
Put
向服务器传输文件
PUT
Cd
进入客户端的目录
不需要与服务端通信,因此无请求
!
cd
进入服务器端目录
CD
Ls
列出客户端当前的内容
不需要与服务端通信因此无请求
!
ls
列出服务器端当前的内容
LS
Connect
连接服务器
发出连接请求,不需要服务器额外处理
Bye
退出程序
BYE
表1_2命令的格式
命令的名称
格式说明
get
getarg1arg2。
arg1:
源文件arg2:
本地路径。
arg1,arg2都是绝对路径
put
putarg1arg1。
arg1:
本地文件arg1:
目标路径。
arg1arg2都是绝对路径
!
cd
!
cdarg1。
arg1:
指定的服务器目录。
绝对路径
!
ls
!
lsarg1。
arg1:
指定的目录。
绝对路径
connect
connectarg1。
arg1:
点分十进制IP地址
cd
cdarg1。
arg1:
客户端的指定目录,绝对路径
ls
lsarg1。
arg1:
客户端指定目录,绝对路径
bye
bye。
1.3.2服务器端
主要任务
1)分析请求代码
2)根据请求代码做相应的处理
3)等待返回结果或者应答信息
表1_3请求码与相应处理
请求代码
对应的处理
GET
向客户端传输文件
PUT
接受客户端的文件
CD
进入目录
LS
将当前目录内容传输给客户端
BYE
断开连接
通信协议与服务器模型:
本项目通信协议分两种
对于get命令和!
ls命令这些需要传输文件内容的命令(!
ls需要传输列出的目录文件列表),采用四次握手的通信协议
如图1_1所示
图1_1四次握手通信协议
以get命令举例,get命令首先发出get请求,服务器程序接收到请求后,发送请求的文件长度或者错误应答码,接收到文件长度后客户端发送RDY应答信息,服务器端开始传输文件内容
对于!
CD命令这种不需要传输文件内容的命令采取两次握手通信协议,如图1_2所示
图1_2两次握手通信协议
本项目服务器采用多线程并发服务器模型,提供和客户端的交互。
3,源代码目录结构
Svr
├───common.h总领整个服务器程序的头文件
├───command.h定义命令处理函数和初始化函数头文件
├───command.c定义命令处理函数和初始化函数
├───main.c定义程序主干函数
└───makefile
Cli
├───common.h总领整个服务器程序的头文件,常用通文件皆放与此
├───command.h定义命令处理函数和初始化函数头文件
├───command.c定义命令处理函数和初始化函数
├───main.c客户端主干函数.
├───input.c定义命令分解函数,用于处理用户输入的命令
└───makefile
4,核心函数及数据结构定义
4.1客户端
intdo_connect(char*ip,int*sock_fd);与服务器端进行连接
intdo_get(constchar*src,constchar*dst,intsock_fd);从远端服务器下载文件
intdo_put(constchar*src,constchar*dst,intsock_fd);向远端服务器上传文件
intdo_cd(char*path);进入当前主机指定目录
intdo_ls(char*path);列出当前主机指定目录下的内容
intdo_serv_cd(char*path,intsock_fd);进入远端服务器指定目录
intdo_serv_ls(char*path,intsock_fd);列出当前服务器目录信息
intbye(intsock_fd);退出服务器,关闭连接
intsplit(structcommamd_line,charline[]);拆分命令相关函数
structcommand_line{
char*name;命令的名称
char*argv[MAX_ARG];命令携带的参数
};
MAX_LINE1024向服务器端发送命令的最大长度
PORT8000端口号
COMMAND_LINE256用户输入客户端命令的最大长度
MAX_LENGTH64每个参数或命令的最大长度
4.2服务器
intdo_get(constchar*src,constchar*dst,intsock_fd);处理用户的put命令
intdo_put(constchar*src,constchar*dst,intsock_fd);处理用户的get命令
intdo_cd(char*path);处理用户的!
cd请求
intdo_ls(char*path);处理用户的!
ls请求
ADDR_LEN17点分十进制IP地址的长度,包括最后的结束符
5,客户端执行流程
5.1输出提示信息
5.2接受用户输入的命令
5.3输入命令是否为空,为空则程序正常退出,非空则继续
5.4输入命令是否为bye,是则程序正常退出,否则继续
5.5处理用户输入的命令
5.6输出提示信息,继续循环执行5.1—5.5的过程
6,服务器执行流程
6.1服务器启动
6.2是否接收到一个连接,是则继续,否则等待
6.3创建连接是否成功,是则继续,否则打印出错信息
6.4创建一个子线程,是则继续,否则打印出错信息
6.5接收客户端传输的命令
6.6解析命令
6.7重复6.2—6.6过程
部分测试命令(取决于你放文件的位置,仅供参考):
put/home/ubuntu/Linux_Ser_Cli/Client/text/a.txt/home/ubuntu/Linux_Ser_Cli/Server/text
put/home/ubuntu/Linux_Ser_Cli/Client/text/user.txt/home/ubuntu/Linux_Ser_Cli/Server/text
get/home/ubuntu/Linux_Ser_Cli/Server/text/b.txt/home/ubuntu/Linux_Ser_Cli/Client/text
源文件:
客户端:
//Clientcommon.h
#pragmaonce
#include
#include
#include"command.h"
//Clientcommand.h
#pragmaonce
#include"common.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineMAX_LINE1024//向服务器端发送命令的最大长度
#definePORT8000//端口号
#defineCOMMAND_LINE256//用户输入客户端命令的最大长度
#defineMAX_LENGTH64//每个参数或命令的最大长度
#defineMAX_ARG4
structcommand_line
{
char*name;//命令的名称
char*argv[MAX_ARG];//命令携带的参数
};
intdo_connect(char*ip,int*sock_fd);//与服务器端进行连接
intdo_get(constchar*src,constchar*dst,intsock_fd);//从远端服务器下载文件
intdo_put(constchar*src,constchar*dst,intsock_fd);//向远端服务器上传文件
intdo_cd(char*path);//进入当前主机指定目录
intdo_ls(char*path);//列出当前主机指定目录下的内容
intdo_serv_cd(char*path,intsock_fd);//进入远端服务器指定目录
intdo_serv_ls(char*path,intsock_fd);//列出当前服务器目录信息
intbye(intsock_fd);//退出服务器,关闭连接
intsplit(structcommand_line*com,charline[]);//拆分命令相关函数
char*path_alloc(size_t*sizep);//获取存放完整路径的内存空间起始地址和大小
intinput();
structcommand_linecomd;
intsock_fd;
intargv;//输入的参数个数
//Clientcommand.c
#include"common.h"
intdo_connect(char*ip,int*sock_fd)//与服务器端进行连接
{
intres;
socklen_tlen;
charbuf[100]="";
structsockaddr_insvraddr,cliaddr;
bzero(&cliaddr,sizeof(cliaddr));//把一段内存区的内容全部设置为0
*sock_fd=socket(PF_INET,SOCK_STREAM,0);
svraddr.sin_family=AF_INET;
svraddr.sin_port=htons(1234);
inet_pton(AF_INET,ip,&(svraddr.sin_addr));
res=connect(*sock_fd,(structsockaddr*)(&svraddr),sizeof(svraddr));
read(*sock_fd,buf,sizeof(buf));
printf("%s\n",buf);//printf("ConnetServerScuess!
\n")
returnres;
}
intdo_cd(char*path)//进入当前主机指定目录
{
char*ptr;//记录改变后的文件目录
size_tsize;
if(chdir(path)<0)
{
perror("chdirfailed!
\n");
}
ptr=path_alloc(&size);//ourownfunction
if(getcwd(ptr,size)==NULL)
{
perror("getcwdfailed!
\n");
}
printf("cwd=%s\n",ptr);
return0;
}
intdo_ls(char*path)//列出当前主机指定目录下的内容
{
DIR*dp;
structdirent*dirp;
if((dp=opendir(path))==NULL)
{
printf("can`topen%s\n",path);
}
while((dirp=readdir(dp))!
=NULL)
{
printf("%s\n",dirp->d_name);
}
closedir(dp);
return0;
}
intdo_put(constchar*src,constchar*dst,intsock_fd)//向远端服务器上传文件
{
FILE*fp;
charb_t[MAX_LENGTH];//记录argv[1]的临时变量
charbuffer[MAX_LINE];
charfile_name[MAX_LENGTH];
intfile_block_length=0;//文件
inti=0.,j=0,len=0;
intres=0;
if(sock_fd>=0)
{
printf("CreateSocketSucess!
\n");
}
else
{
perror("Failed!
\n");
exit
(1);
}
write(sock_fd,comd.name,sizeof(comd.name));//向服务器发送操作符
printf("comd.name:
%s\n",comd.name);
bzero(buffer,sizeof(buffer));
strcpy(buffer,src);
send(sock_fd,buffer,sizeof(buffer),0);
//send(sock_fd,src,sizeof(src),0);
printf("src:
%s\n",buffer);
bzero(buffer,sizeof(buffer));
strcpy(buffer,dst);
send(sock_fd,buffer,sizeof(buffer),0);
printf("dst:
%s\n",buffer);
recv(sock_fd,buffer,sizeof(buffer),0);//Ready
printf("buffer:
%s\n",buffer);
if(strcmp(buffer,"Ready")==0)
{
bzero(buffer,sizeof(buffer));
strcpy(b_t,src);
len=strlen(b_t);
i=len-1;
while(b_t[i]!
='/')/*提取文件名*/
{
i--;
}
i++;
while(i { file_name[j++]=b_t[i]; i++; } file_name[j]='\0'; send(sock_fd,file_name,sizeof(file_name),0); printf("SendServerFileName: %s\n",file_name); bzero(buffer,sizeof(buffer)); recv(sock_fd,buffer,sizeof(buffer),0); printf("RecvFromServer: %s\n",buffer);//OK bzero(buffer,sizeof(buffer)); fp=fopen(src,"r"); if(NULL==fp) { printf("File: \t%sNotFound\n",file_name); } else { bzero(buffer,sizeof(buffer)); while((file_block_length=fread(buffer,sizeof(char),MAX_LINE,fp))>0) { printf("file_block_length=%d\n",file_block_length); res=send(sock_fd,buffer,file_block_length+1,0); if(res<0) { printf("SendFile: \t%sFailed\n",file_name); break; } bzero(buffer,sizeof(buffer)); } /*这段代码是循环读取文件的一段数据,在循环调用send,发送到客户端,这里强调一点的TCP每次接受最多是1024字节 多了就会分片,因此每次发送时尽量不要超过1024字节。 */ fclose(fp); printf("File: \t%sTransferFinished\n",file_name); } } else { printf("NOTReady! \n"); } return0; } intdo_get(constchar*src,constchar*dst,intsock_fd)//从远端服务器下载文件 { intlength=0; intwrite_length;//写入文件长度 charfile_name[MAX_LENGTH]; charbuffer[MAX_LINE]; charb_t[MAX_LENGTH];//记录argv[1]的临时变量 FILE*fp; inti=0,len=0,j=0; if(sock_fd<0) { printf("CreateSocketFailed! \n"); exit (1); } else { printf("CreatSocketScuess! \n"); } write(sock_fd,comd.name,sizeof(comd.name));//向服务器发送操作符 printf("comd.name: %s\n",comd.name); bzero(buffer,sizeof(buffer)); strcpy(buffer,src); send(sock_fd,buffer,sizeof(buffer),0); printf("src: %s\n",buffer); bzero(buffer,sizeof(buffer)); strcpy(buffer,dst); send(sock_fd,buffer,sizeof(buffer),0); printf("dst: %s\n",buffer); bzero(buffer,sizeof(buffer)); recv(sock_fd,buffer,sizeof(buffer),0);//Ready printf("FromServer: %s\n",buffer); if(strcmp(buffer,"Ready")==0) { bzero(buffer,sizeof(buffer)); bzero(file_name,sizeof(file_name)); strcpy(b_t,src); len=strlen(b_t);/*提取文件名*/ i=len-1; while(b_t[i]! ='/') { i--; } i++; while(i { file_name[j++]=b_t[i]; i++; } send(sock_fd,file_name,sizeof(file_name),0); printf("FileName: %s\n",file_name); strcpy(buffer,dst);//连接文件名和所要放的文件夹位置 strcat(buffer,"/"); strncat(buffer,file_name,strlen(file_name)); fp=fopen(buffer,"w+"); if(NULL==fp) { printf("File: \t%sCanNotOpenToWrite\n",file_name); } //从服务器接收数据到buffer中 bzero(buffer,sizeof(buffer)); while((length=recv(sock_fd,buffer,sizeof(buffer),0))>0)//循环接收,再写到文件 { printf("length: %d\n",length); write_length=fwrite(buffer,sizeof(char),length-1,fp); if(write_length==length) { if(write_length break; } bzero(buffer,sizeof(buffer)); } if(length<0) { printf("RecieveDataFromServer%sFailed! \n",src); exit (1); } printf("RecieveFile: \t%sFromServer[%s]Finished\n",file_name,src); fclose(fp); } else { printf("NOTReady! \n"); } return0; } intdo_serv_cd(char*path,intsock_fd)//进入远端服务器指定目录 { charbuf[MAX_LINE]=""; write(sock_fd,comd.name,sizeof(comd.name));//首先发送操作符 strcpy(buf,path); printf("sendtoserver: %s\n",buf); send(sock_fd,buf,sizeof(buf),0); bzero(buf,sizeof(buf
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Llinux 微型 文件传输 要点
![提示](https://static.bdocx.com/images/bang_tan.gif)