当前位置:文档之家› 文件传输协议的设计与实现

文件传输协议的设计与实现

课程设计任务书

学生姓名:专业班级:

指导教师:工作单位:信息工程学院

题目:文件传输协议的设计与实现

初始条件:

Windows XP

C++,SOCKET

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)

1.掌握TCP/IP 网络应用程序基本的设计方法;

2.用socket 编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c);

3.撰写课程设计说明书。装订后的课程设计说明书不少于10面(含封面、任务书、目录、正文、参考文献、成绩评定表、封底)。

时间安排:

6月18日查阅资料、方案论证

6月19日方案设计、调试

6月20日撰写课程设计说明书

6月21日答辩

指导教师签名:年月日

系主任(或责任教师)签名:年月日

运行正确的程序::

1.服务器源代码:

#include

#include

#include

using namespace std;

#pragma comment(lib, "wsock32.lib")

#define PORT 4523

char 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);//定义为面向连接的,返回值送给sockSrv

if(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);

}

/*MAX_PATH是C语言运行时库中通过#define指令定义的一个宏常量,它定义了编译器所支持的最长全路径名的长度。

在VC++6.0中,_MAX_PATH的值为260。

*/

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?"

":" ";

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!"<

if(send(datatcps,errstr,strlen(errstr),0)==SOCKET_ERROR)

{

cout<<"error occurs when sending file list!"<

}

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!"<

return(-1);

}

cout<<"Listening for the request……"<

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"<

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<

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,"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);}

}//file

else//打开文件失败

{

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

#include

#include

using namespace std;//使用名称空间std

#pragma comment(lib, "wsock32.lib")//将WinLib.lib库加入到工程中进行编译

#define PORT 4523//定义端口号为4523

char 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:"<

cout<<"dir………………………………directory list "<

cout<<"get………………………………download files"<

cout<<"put………………………………upload files "<

cout<<"quit………………………………exit !"<

}

//list读取服务器列表

void list(SOCKET sock)

{

int nRead;

while(true)

{

nRead=recv(sock,rec_str,1024,0);//从一个套接口接收数据

if(nRead==SOCKET_ERROR)

{

cout<<"read response error!"<

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.."<

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 :"<

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<<"send data error!"<

closesocket(sockClient);

WSACleanup();

return 0;

}

recv(sockClient,rec_str,1024,0);//接受链接数据,放入rec_str

cout<

if(strncmp(command,"quit",4)==0)

{

closesocket(sockClient);

WSACleanup();

return 0;

}//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("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);

}//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("send failed!");

return 0;

}

fclose(fd2);

}

else//打开文件失败

{

strcpy(send_str,"can't open file!\n");

if(send(sockClient,send_str,1024,0))

return 0;

}

}//put

closesocket(sockClient);

WSACleanup();

return Cprocess();

}

int main()

{

help();

Cprocess();

return 0;

}

3.程序运行结果

一.正确功能实现

1.运行客户端,输入服务器正确IP地址,连接成功后,输入dir查看服务器

所在文件夹中的文件

2.用put命令发送文件p.txt,发送完毕,查看服务器所在文件夹,发现p.txt

存在

3.使用put命令

使用前,服务器所在文件如下

对话框中输入put p.txt

4.使用get命令

使用前,客户端所在文件夹文件如下图

在对话框中输入 get g.exe

再看文件夹,发现出现g.exe

以上三步完成后,看服务器端窗口显示

二.运行错误测试

1.运行客户端,输入错误的IP地址。输入请求后,显示框直接关闭

2.发送客户端文件夹中不存在的文件(c.txt)时,客户端显示框直接关闭,服

务器端显示为

3.下载服务器文件夹文件时,服务器端直接关闭,客户端显示框如下

4.输入错误指令时,客户端显示如下,显示后,无法输入任何文字

服务器显示如下

相关主题