实验一文件传输协议设计要点.docx
《实验一文件传输协议设计要点.docx》由会员分享,可在线阅读,更多相关《实验一文件传输协议设计要点.docx(18页珍藏版)》请在冰豆网上搜索。
实验一文件传输协议设计要点
实验一:
文件传输协议的设计与实现
目录
1.实验设计目的和要求
2.背景知识
3.课程设计分析
4.程序清单
5.运行结果
6.总结
1.课程设计目的和要求
文件传输是各种计算机的网络的基本功能,文件传送协议是一种最基本的应用层协议。
它是按照客户或服务器模式进行的工作,提供交式的访问。
是INTERNRT使用最广泛的协议之一。
以及深入了解计算机网络是建立在TCP/IP网络体系结构上。
用socket编程接口编写俩个程序,分别为客户程序和服务器程序
1.掌握TCP/IP网络应用程序基本的设计方法;
2.用socket编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c);
3.撰写课程设计说明书。
装订后的课程设计说明书不少于10面(含封面、任务书、目录、正文、参考文献、成绩评定表、封底)。
2.背景知识
第一个FTP的RFC由A.K.Bhushan在1971年提出,同时由MIT与Harvard实验实现,RFC172提供了主机间文件传输的一个用户级协议。
长期发展过程由于底层协议从NCP改变为TCP,RFC765定义了采用TCP的FCP.
FTP协议在今天已经发展成熟,应用也越来越广很多开发的比较成熟的FTP客户端软件已经得到了广泛的应用.
3.课程设计分析
Server端Client端
创建ServerSocket对象,在某端口提供监听服务Client端
等待来自Client端的服务请求
接受Client端的请求,用返回的创建Socket对象,向Server
Socket建立连接的监听端口请求
通过向Socket中读写数据来通过向新的Socket中读写数
与Client端通信据来与Server端通信
关闭Socket,结束与Server端的通信关闭Socket,结束与当前
Client的通信,等待其他请求
关闭ServerSocket对象,结束监听服务
4.程序清单:
1.服务器源代码:
#include
#include
#include
usingnamespacestd;
#pragmacomment(lib,"wsock32.lib")
#definePORT4523
charbuf_send[1024];
charbuf_rec[1024];
SOCKETsockSrv;
//socket初始化
DWORDCreateSocket()
{
WSADATAWSAData;//WSADATA结构被用来保存函数WSAStartup返回的WindowsSockets初始化信息
if(WSAStartup(MAKEWORD(2,2),&WSAData)!
=0)//WSAStartup完成winsock的初始化
{printf("socketinitializefailed!
\n");
return(-1);
}
sockSrv=socket(AF_INET,SOCK_STREAM,0);//定义为面向连接的,返回值送给sockSrv
if(sockSrv==SOCKET_ERROR)
{
printf("socketcreatefailed!
\n");
WSACleanup();//中止WindowsSocketsDLL的使用
return(-1);
}
SOCKADDR_INaddrSrv;//TCP/IP使用SOCKADDR_IN定义地址
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//计算机IP地址
addrSrv.sin_port=htons(PORT);//协议端口号
addrSrv.sin_family=AF_INET;//地址所属协议簇
//绑定端口
if(bind(sockSrv,(structsockaddrFAR*)&addrSrv,sizeof(addrSrv))==SOCKET_ERROR)
{
printf("BindError");
return(-1);
}
return
(1);
}
intSendFileRecord(SOCKETdatatcps,WIN32_FIND_DATA*pfd)//用于回复给客户端
{
charfilerecord[MAX_PATH+32];
FILETIMEft;
FileTimeToLocalFileTime(&pfd->ftLastWriteTime,&ft);//将一个FILETIME结构转换成本地时间
SYSTEMTIMElastwtime;//系统时间
FileTimeToSystemTime(&ft,&lastwtime);//根据一个FILETIME结构的内容,装载一个SYSTEMTIME结构
char*dir=pfd->dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY?
"
":"";
sprintf(filerecord,"%04d-%02d-%02d%02d:
%02d%5s%10d%-20s\n",
lastwtime.wYear,
lastwtime.wMonth,
lastwtime.wDay,
lastwtime.wHour,
lastwtime.wMinute,
dir,
pfd->nFileSizeLow,
pfd->cFileName);
if(send(datatcps,filerecord,strlen(filerecord),0)==SOCKET_ERROR)//发送回复失败
{
printf("Erroroccurswhensendingfilelist!
\n");
return0;
}
return1;
}
//发送主机文件目录
intSendFileList(SOCKETdatatcps)
{
HANDLEhff;
WIN32_FIND_DATAfd;//获取和更改文件属性
hff=FindFirstFile("*",&fd);//搜索文件
if(hff==INVALID_HANDLE_VALUE)//搜索无效返回值
{
constchar*errstr="can'tlistfiles!
\n";
cout<<"listfileerror!
"<if(send(datatcps,errstr,strlen(errstr),0)==SOCKET_ERROR)
{
cout<<"erroroccurswhensendingfilelist!
"<}
closesocket(datatcps);
return0;
}
BOOLfMoreFiles=TRUE;//BOOL型,返回值为大于0的整数时为TRUE,返回值为0时候,为FALSE,返回值为-1时为ERROR。
while(fMoreFiles)
{
//发送此项文件信息
if(!
SendFileRecord(datatcps,&fd))//发送失败
{
closesocket(datatcps);
return0;
}
//搜索下一个文件
fMoreFiles=FindNextFile(hff,&fd);
}
closesocket(datatcps);
return1;
}
//发送数据
intSendFile(SOCKETdatatcps,FILE*file)//发送文件
{
printf("sendingfiledata..");
for(;;)
//从文件中循环读取数据并发送客户端
{
intr=fread(buf_send,1,1024,file);
if(send(datatcps,buf_send,r,0)==SOCKET_ERROR)
{
printf("losttheconnectiontoclient!
\n");
closesocket(datatcps);
return0;
}
if(r<1024)//文件传送结束
break;
}
closesocket(datatcps);
printf("done\n");
return1;
}
DWORDProcessCmd()
{
if(listen(sockSrv,5)<0)//监听信号
{
cout<<"Listenerror!
"<return(-1);
}
cout<<"Listeningfortherequest……"<SOCKADDR_INaddrclient;//定义用于返回客户机端地址的结构
intlen=(sizeof(SOCKADDR_IN));
while
(1)
{
SOCKETsockconn=accept(sockSrv,(SOCKADDR*)&addrclient,&len);//接受请求,产生新的套接字
if(sockconn==INVALID_SOCKET)
continue;
elsecout<<"connectingfromclient"<while(true)
{
charfilename[20];
memset(buf_rec,0,1024);
memset(buf_send,0,1024);
if(recv(sockconn,buf_rec,1024,0)<=0)
{
break;
}
cout<"<if(strncmp(buf_rec,"dir",3)!
=0&&strncmp(buf_rec,"get",3)!
=0&&strncmp(buf_rec,"put",3)!
=0)
continue;//有一个请求正确执行下面语句
if(strncmp(buf_rec,"dir",3)==0)
{
strcpy(buf_send,"dir-ing\n");
send(sockconn,buf_send,1024,0);
SendFileList(sockconn);//发送当前所有文件名
}//dir
if(strncmp(buf_rec,"get",3)==0)
{
strcpy(filename,buf_rec+4);
cout<FILE*file;
//处理下载文件请求
file=fopen(filename,"rb");//打开下载的文件
if(file)
{
sprintf(buf_send,"getfile%s\n",filename);
if(!
send(sockconn,buf_send,1024,0))
{fclose(file);
return0;}
else
{//创建额外数据连接传送数据
if(!
SendFile(sockconn,file))
return0;
fclose(file);}
}//file
else//打开文件失败
{
strcpy(buf_send,"can'topenfile!
\n");
if(send(sockconn,buf_send,1024,0))
return0;
}
}//get处理客户端的下载请求
if(strncmp(buf_rec,"put",3)==0)
{
FILE*fd;
intcount;
strcpy(filename,buf_rec+4);
fd=fopen(filename,"wb");
if(fd==NULL)
{
printf("openfile%sforweitefailed!
\n",filename);
continue;
}
sprintf(buf_send,"putfile%s",filename);
if(!
send(sockconn,buf_send,1024,0))
{fclose(fd);
return0;
}
while((count=recv(sockconn,buf_rec,1024,0))>0)
fwrite(buf_rec,sizeof(char),count,fd);
fclose(fd);
continue;
}//put处理客户端的上传请求
}
}
}
intmain()
{
CreateSocket();
ProcessCmd();
return
(1);
}
2.客户端程序源代码:
#include
#include
#include
usingnamespacestd;//使用名称空间std
#pragmacomment(lib,"wsock32.lib")//将WinLib.lib库加入到工程中进行编译
#definePORT4523//定义端口号为4523
charsend_str[1024];
charrec_str[1024];
charIP[20];
charfilename[20];
SOCKETsockClient;
SOCKADDR_INaddrServer;//定义表示地址的结构体addrServer,用来表示本地地址
//创建套接字
DWORDCreateSock()
{
//本地信息
addrServer.sin_family=AF_INET;//地址所属协议簇
//AF表示ADDRESSFAMILY地址族
//htons的功能:
将一个无符号短整型数值转换为网络字节序
addrServer.sin_port=htons(PORT);//协议端口号
WSADATAWSAData;//WSADATA结构被用来保存函数WSAStartup返回的WindowsSockets初始化信息
WORDwVersionRequsdted;
interr;
wVersionRequsdted=MAKEWORD(2,2);
err=WSAStartup(wVersionRequsdted,&WSAData);
if(err!
=0){
printf("sockinitfail!
\n");
return(-1);
}
cout<<"pleaseinputtheIPofhost:
";
scanf("%s",&IP);
addrServer.sin_addr.s_addr=inet_addr(IP);//计算机IP地址
return
(1);
}
DWORDConnectServer()//连接服务器
{
sockClient=socket(AF_INET,SOCK_STREAM,0);//创建套接字,SOCK_STREAM为面向连接型
if(sockClient==SOCKET_ERROR)
{
printf("sockcreatefail!
\n");
WSACleanup();//中止WindowsSocketsDLL的使用.
return(-1);
}
if(connect(sockClient,(structsockaddr*)&addrServer,sizeof(addrServer))==SOCKET_ERROR)//如果请求建立连接错误
{
printf("Connectfail\n");
memset(IP,0,20);
return(-1);
}
return
(1);
}
voidhelp()
{
cout<<"helpList:
"<cout<<"dir………………………………directorylist"<cout<<"get………………………………downloadfiles"<cout<<"put………………………………uploadfiles"<cout<<"quit………………………………exit!
"<}
//list读取服务器列表
voidlist(SOCKETsock)
{
intnRead;
while(true)
{
nRead=recv(sock,rec_str,1024,0);//从一个套接口接收数据
if(nRead==SOCKET_ERROR)
{
cout<<"readresponseerror!
"<exit
(1);
}
if(nRead==0)//数据读取结束
break;
//显示数据
rec_str[nRead]='\0';
printf("%s",rec_str);
}
}
intSendFile(SOCKETdatatcps,FILE*file)//SOCKETdatatcps定义变量数据连接套接字
{
cout<<"sendingfiledata.."<for(;;)
{
intr=fread(send_str,1,1024,file);//从一个流中读数据
if(send(datatcps,send_str,r,0)==SOCKET_ERROR)
{
printf("losttheconnectiontoclient!
\n");
closesocket(datatcps);
return0;
}
if(r<1024)//文件传送结束
break;
}
closesocket(datatcps);//关闭接口
printf("done\n");
return
(1);
}
intCprocess()
{
intcount;
charorder[10];
charparam[20];
charcommand[30];
FILE*fd;
FILE*fd2;
command[0]='\0';
CreateSock();
ConnectServer();
cout<<"pleaseinputorder:
"<memset(order,0,10);//初始化为0
memset(param,0,20);//初始化为0
memset(command,0,30);//初始化为0
memset(rec_str,0,1024);//初始化为0
memset(send_str,0,1024);//初始化为0
cin>>order;
strcat(command,order);
if(strncmp(order,"get",3)==0||strncmp(order,"put",3)==0)//输入请求,有一个输入要求正确,输入目标文件名
{
cin>>param;
strcat(command,"");
strcat(command,param);
}
cout<strcpy(send_str,command);
if(send(sockClient,send_str,sizeof(send_str),0)<0)
{
cout<<"senddataerror!
"<closesocket(sockClient);
WSACleanup();
return0;
}
recv(sockClient,rec_str,1024,0);//接受链接数据,放入rec_str
cout<if(strncmp(command,"quit",4)==0)
{
closesocket(sockClient);
WSACleanup();
return0;
}//quit
if(strncmp(rec_str,"dir",3)==0)
{
list(sockClient);
}//dir
if(strncmp(rec_str,"get",3)==0)
{
fd=fopen(param,"wb");//使用二进制方式创建并打开名为param的文件
if(fd==NULL)//打开失败
{
printf("openfile%sforweitefailed!
\n",param);
return0;
}
while((count=recv(sockClient,rec_str,1024,0))>0)//接收文件,放入rec_str
{
fwrite(rec_str,sizeof(char),count,fd);}
fclose(fd);
}//get
if(strncmp(rec_str,"put",3)==0)
{
strcpy(filename,rec_str+9);//复制需发送的文件名称,赋给filename
fd2=fopen(filename,"rb");
if(fd2)//假如读文件成功
{
if(!
SendFile(sockClient,fd2))//假如发送失败
{
printf("sendfa