当前位置:文档之家› (完整)实验一-文件传输协议设计要点

(完整)实验一-文件传输协议设计要点

实验一:文件传输协议的设计与实现目录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实验实现,RFC 172提供了主机间文件传输的一个用户级协议。

长期发展过程由于底层协议从NCP改变为TCP,RFC765定义了采用TCP的FCP.FTP协议在今天已经发展成熟,应用也越来越广很多开发的比较成熟的FTP 客户端软件已经得到了广泛的应用.3.课程设计分析Server端Client端创建ServerSocket对象,在某端口提供监听服务Client端等待来自Client端的服务请求接受Client端的请求,用返回的创建Socket对象,向ServerSocket建立连接的监听端口请求通过向Socket中读写数据来通过向新的Socket中读写数与Client端通信据来与Server端通信关闭Socket,结束与Server端的通信关闭Client的通信,等待其他请求关闭ServerSocket对象,结束监听服务4.程序清单:1.服务器源代码:#include <Winsock2.h>#include <stdio.h>#include <iostream>using namespace std;#pragma comment(lib, "wsock32.lib")#define PORT 4523char buf_send[1024];char buf_rec[1024];SOCKET sockSrv;//socket初始化DWORD CreateSocket(){WSADATA WSAData;//WSADATA结构被用来保存函数WSAStartup返回的Windows Sockets初始化信息if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)//WSAStartup完成winsock的初始化{printf("socket initialize failed!\n");return (-1);}sockSrv=socket(AF_INET,SOCK_STREAM,0);//定义为面向连接的,返回值送给sockSrvif(sockSrv==SOCKET_ERROR){printf("socket create failed ! \n");WSACleanup();//中止Windows Sockets DLL的使用return(-1);}SOCKADDR_IN addrSrv;//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,(struct sockaddr FAR *)&addrSrv,sizeof(addrSrv))==SOCKET_ERROR){printf("Bind Error");return(-1);}return (1);}int SendFileRecord(SOCKET datatcps,WIN32_FIND_DATA *pfd)//用于回复给客户端{char filerecord[MAX_PATH+32];FILETIME ft;FileTimeToLocalFileTime(&pfd->ftLastWriteTime,&ft);//将一个FILETIME结构转换成本地时间SYSTEMTIME lastwtime;//系统时间FileTimeToSystemTime(&ft,&lastwtime);//根据一个FILETIME结构的内容,装载一个SYSTEMTIME 结构char *dir=pfd->dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY?"<DIR>":" ";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("Error occurs when sending file list!\n");return 0;}return 1;}//发送主机文件目录int SendFileList(SOCKET datatcps){HANDLE hff;WIN32_FIND_DATA fd; //获取和更改文件属性hff=FindFirstFile("*",&fd);//搜索文件if(hff==INVALID_HANDLE_VALUE)//搜索无效返回值{const char *errstr="can't list files!\n";cout<<"list file error!"<<endl;if(send(datatcps,errstr,strlen(errstr),0)==SOCKET_ERROR){cout<<"error occurs when sending file list!"<<endl;}closesocket(datatcps);return 0;}BOOL fMoreFiles=TRUE;//BOOL型,返回值为大于0的整数时为TRUE,返回值为0时候,为FALSE,返回值为-1时为ERROR。

while(fMoreFiles){//发送此项文件信息if(!SendFileRecord(datatcps,&fd))//发送失败{closesocket(datatcps);return 0;}//搜索下一个文件fMoreFiles=FindNextFile(hff,&fd);}closesocket(datatcps);return 1;}//发送数据int SendFile(SOCKET datatcps,FILE* file)//发送文件{printf("sending file data..");for(;;)//从文件中循环读取数据并发送客户端{int r=fread(buf_send,1,1024,file);if(send(datatcps,buf_send,r,0)==SOCKET_ERROR){printf("lost the connection to client!\n");closesocket(datatcps);return 0;}if(r<1024)//文件传送结束break;}closesocket(datatcps);printf("done\n");return 1;}DWORD ProcessCmd(){if(listen(sockSrv,5)<0)//监听信号{cout<<"Listen error!"<<endl;return(-1);}cout<<"Listening for the request……"<<endl;SOCKADDR_IN addrclient;//定义用于返回客户机端地址的结构int len=(sizeof(SOCKADDR_IN));while(1){SOCKET sockconn=accept(sockSrv,(SOCKADDR*)&addrclient,&len);//接受请求,产生新的套接字if(sockconn==INVALID_SOCKET)continue;else cout<<"connecting from client"<<endl;while(true){char filename[20];memset(buf_rec,0,1024);memset(buf_send,0,1024);if(recv(sockconn,buf_rec,1024,0)<=0){break;}cout<<endl<<"the command is:"<<buf_rec<<endl;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);//发送当前所有文件名}//dirif (strncmp(buf_rec,"get",3)==0){strcpy(filename,buf_rec+4);cout<<filename;FILE *file;//处理下载文件请求file=fopen(filename,"rb");//打开下载的文件if(file){sprintf(buf_send,"get file %s\n",filename);if(!send(sockconn,buf_send,1024,0)){fclose(file);return 0;}else{//创建额外数据连接传送数据if(!SendFile(sockconn,file))return 0;fclose(file);}}//fileelse//打开文件失败{strcpy(buf_send,"can't open file!\n");if(send(sockconn,buf_send,1024,0))return 0;}}//get 处理客户端的下载请求if(strncmp(buf_rec,"put",3)==0){FILE *fd;int count;strcpy(filename,buf_rec+4);fd=fopen(filename,"wb");if(fd==NULL){printf("open file %s for weite failed!\n",filename);continue;}sprintf(buf_send,"put file %s",filename);if(!send(sockconn,buf_send,1024,0)){ fclose(fd);return 0;}while((count=recv(sockconn,buf_rec,1024,0))>0)fwrite(buf_rec,sizeof(char),count,fd);fclose(fd);continue;}//put 处理客户端的上传请求}}}int main(){CreateSocket();ProcessCmd();return(1);}2. 客户端程序源代码:#include <Winsock2.h>#include <stdio.h>#include <iostream>using namespace std;//使用名称空间std#pragma comment(lib, "wsock32.lib")//将WinLib.lib库加入到工程中进行编译#define PORT 4523//定义端口号为4523char send_str[1024];char rec_str[1024];char IP[20];char filename[20];SOCKET sockClient;SOCKADDR_IN addrServer;//定义表示地址的结构体addrServer,用来表示本地地址//创建套接字DWORD CreateSock(){//本地信息addrServer.sin_family=AF_INET;//地址所属协议簇//AF表示ADDRESS FAMILY 地址族// htons的功能:将一个无符号短整型数值转换为网络字节序addrServer.sin_port=htons(PORT);//协议端口号WSADATA WSAData;//WSADATA结构被用来保存函数WSAStartup返回的Windows Sockets初始化信息WORD wVersionRequsdted;int err;wVersionRequsdted=MAKEWORD(2,2);err=WSAStartup(wVersionRequsdted,&WSAData);if(err!=0){printf("sock init fail!\n");return(-1);}cout<<"please input the IP of host:";scanf("%s",&IP);addrServer.sin_addr.s_addr=inet_addr(IP);//计算机IP地址return(1);}DWORD ConnectServer() //连接服务器{sockClient=socket(AF_INET,SOCK_STREAM,0);//创建套接字,SOCK_STREAM为面向连接型if(sockClient==SOCKET_ERROR){printf("sock create fail! \n");WSACleanup();//中止Windows Sockets DLL的使用.return(-1);}if(connect(sockClient,(struct sockaddr *)&addrServer,sizeof(addrServer))==SOCKET_ERROR)//如果请求建立连接错误{printf("Connect fail \n");memset(IP,0,20);return(-1);}return(1);}void help(){cout<<"help List:"<<endl;cout<<"dir………………………………directory list "<<endl;cout<<"get………………………………download files"<<endl;cout<<"put………………………………upload files "<<endl;cout<<"quit………………………………exit !"<<endl;}//list读取服务器列表void list(SOCKET sock){int nRead;while(true){nRead=recv(sock,rec_str,1024,0);//从一个套接口接收数据if(nRead==SOCKET_ERROR){cout<<"read response error!"<<endl;exit(1);}if(nRead==0)//数据读取结束break;//显示数据rec_str[nRead]='\0';printf("%s",rec_str);}}int SendFile(SOCKET datatcps,FILE* file)//SOCKET datatcps定义变量数据连接套接字{cout<<"sending file data.."<<endl;for(;;){int r=fread(send_str,1,1024,file);//从一个流中读数据if(send(datatcps,send_str,r,0)==SOCKET_ERROR){printf("lost the connection to client!\n");closesocket(datatcps);return 0;}if(r<1024)//文件传送结束break;}closesocket(datatcps);//关闭接口printf("done\n");return(1);}int Cprocess(){int count;char order[10];char param[20];char command[30];FILE *fd;FILE *fd2;command[0]='\0';CreateSock();ConnectServer();cout<<"please input order :"<<endl;memset(order,0,10);//初始化为0memset(param,0,20);//初始化为0memset(command,0,30);//初始化为0memset(rec_str,0,1024);//初始化为0memset(send_str,0,1024);//初始化为0cin>>order;strcat(command,order);if(strncmp(order,"get",3)==0||strncmp(order,"put",3)==0)//输入请求,有一个输入要求正确,输入目标文件名{cin>>param;strcat(command," ");strcat(command,param);}cout<<command<<endl;strcpy(send_str,command);if(send(sockClient,send_str,sizeof(send_str),0)<0){cout<<"send data error!"<<endl;closesocket(sockClient);WSACleanup();return 0;}recv(sockClient,rec_str,1024,0);//接受链接数据,放入rec_strcout<<rec_str<<endl;if(strncmp(command,"quit",4)==0){closesocket(sockClient);WSACleanup();return 0;}//quitif(strncmp(rec_str,"dir",3)==0){list(sockClient);}//dirif(strncmp(rec_str,"get",3)==0){fd=fopen(param,"wb");//使用二进制方式创建并打开名为param的文件if(fd==NULL) //打开失败{printf("open file %s for weite failed!\n",param);return 0;}while((count=recv(sockClient,rec_str,1024,0))>0)//接收文件,放入rec_str{fwrite(rec_str,sizeof(char),count,fd);}fclose(fd);}//getif(strncmp(rec_str,"put",3)==0){strcpy(filename,rec_str+9);//复制需发送的文件名称,赋给filenamefd2=fopen(filename,"rb");if(fd2)//假如读文件成功{if(!SendFile(sockClient,fd2))//假如发送失败{printf("send failed!");return 0;}fclose(fd2);}else//打开文件失败{strcpy(send_str,"can't open file!\n");if(send(sockClient,send_str,1024,0))return 0;}}//putclosesocket(sockClient);WSACleanup();return Cprocess();}int main(){help();Cprocess();return 0;}5.程序运行结果一.正确功能实现1.运行客户端,输入服务器正确IP地址,连接成功后,输入dir查看服务器所在文件夹中的文件2.用put命令发送文件p.txt,发送完毕,查看服务器所在文件夹,发现p.txt存在二.运行错误测试1.运行客户端,输入错误的IP地址。

相关主题