已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
精品文库课 程 设 计 课程名称_题目名称_学生学院_专业班级_学 号_学生姓名_指导教师_200 年 月 日摘要本课程设计说明书主要说明了在windows下如何用c语言编写设计ftp服务器和客户端的基本方法及其实现。包含了TCP/IP协议基本通信原理,Winsock编程基本原理以及ftp工作原理。正文部分是程序设计的具体内容及其源代码,最后是报告反思及总结。关键词:TCP/IP,Winsock,ftp欢迎下载摘要11.绪 论11.1设计目的11.2设计要求11.21计算机网络实验环境建立在TCP/IP 网络体系结构之上。11.22具体要求11.3设计准备21.4设计方案22.开发环境介绍23.相关原理分析了解33.1TCP/IP原理33.11网络层协议33.12应用层协议33.2Winsock编程原理33.23Winsock编程模型:4数据报套接字编程模型4Winsock I/O模型53.3TP工作原理53.4Winsock API基本函数介绍5(1)WSAStartup()函数和WSACleanup()函数5(2)socket()函数6(3)bind( ) 函数6(4)listen( )函数6(5)accept( )函数6(6)connect( )函数6(7)closesocket( )函数74.总体设计74.1了解Winsock与操作系统的关系74.2实现功能流程图85.详细设计85.1文件传输源程序代码8(1)客户端client程序代码8(2)、服务器端server程序代码14六、系统实现步骤19七、总结结论(心得体会)21参考文献:22欢迎下载1.绪 论1.1设计目的 本设计旨在利用原始socket简单实现FTP(File Transfer Protocol,文件传输协议)的客户端和服务器端程序,能够实现get、put、pwd、dir、cd等基本交互命令。通过完成此设计,了解Winsock API函数调用方法和一般网络应用程序的编程方法,理解FTP协议,掌握C语言设计FTP协议软件的基本技术,为将来开发其他通信协议软件打下坚实基础。1.2设计要求 1.21计算机网络实验环境建立在TCP/IP 网络体系结构之上。各计算机除了安装TCP/IP 软件外,还安装了TCP/IP 开发系统。实验室各计算机具备Windows环境中套接字socket 的编程接口功能,可为用户提供全网范围的进程通信功能。本实验要求学生利用这些功能,设计和实现一个简单的文件传送协议。 1.22具体要求 用socket 编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c),该程序应能实现下述命令功能: get:取远方的一个文件 put:传给远方一个文件 pwd:显示远主当前目录 dir:列出远方当前目录 cd :改变远方当前目录 ? :显示你提供的命令 quit :退出返回1.3设计准备装有Windows操作系统的PC机、Visual C+ 6.0编译器或VS2010编译器1.4设计方案 1.服务器端调用socket的accept()方法,等待客户端联接。 2.客户端发送需要从服务端获得的文件夹路径给服务器端。 3.服务器端根据客户端发来的路径遍历整个路径下的文件及文件夹,并将需要传送到文件记录全路径记录到一个String类型的数组中,并将文件的个数发送给客户端。 4.客户端接收服务器端发来的文件个数,并向服务器端发送关闭联接请求,并关闭客户端连接。 5.服务器端收取关闭连接请求,将socket关闭,进入传输文件循环中。 6.服务器端调用socket的accept()方法,等待客户端联接。7.客户端根据刚才取得的要传输的文件数,进行循环获取文件,记得每次取完文件要关闭socket连接,这样就不会将多个文件写入到同一个文件中。2.开发环境介绍VC6.0编程环境:首先建一个工程,填入文件名,点击下一步,出现要创建的文件夹名,填上点击下一步,完成建立工程。然后再点击新建菜单,新建一个C/C+source文件,点击下一步,完成建立过程,然后在窗口中写入源代码,执行即可。3.相关原理分析了解3.1TCP/IP原理 TCP协议和IP协议指两个用在Internet上的网络协议(或数据传输的方法)。它们分别是传输控制协议和互连网协议。这两个协议属于众多的TCP/IP协议组中的一部分。TCP/IP协议组中的协议保证Internet上数据的传输,提供了几乎现在上网所用到的所有服务。这些服务包括:电子邮件的传输 ,文件传输 , 新闻组的发布 , 访问万维网 在TCP/IP协议组分两种协议:网络层的协议和应用层的协议 3.11网络层协议:网络层协议管理离散的计算机间的数据传输。这些协议用户注意不到,是在系统表层以下工作的。比如,IP协议为用户和远程计算机提供了信息包的传输方法。它是在许多信息的基础上工作的,比如说是机器的IP地址。在机器IP地址和其它信息的基础上,IP确保信息包能正确地到达目的机器。通过这一过程,IP和其它网络层的协议共同用于数据传输。如果没有网络工具,用户就看不到在系统里工作的IP。 3.12应用层协议: 相反地,应用层协议用户是可以看得到的。比如,文件传输协议(FTP)用户是看得到的。用户为了传输一个文件请求一个和其它计算机的连接,连接建立后,就开始传输文件。在传输时,用户和远程计算机的交换的一部分是能看到的。 TCP/IP通过使用协议栈工作。这个栈是所有用来在两台机器间完成一个传输的所有协议的几个集合。(这也就是一个通路,数据通过它从一台机器到另一台机器。)栈分成层,与这里有关的是五个层。栈的每一层都能从相邻的层中接收或发送数据。每一层都与许多协议相联系。在栈的每一层,这些协议都在起作用。本章的下一部分将分析这些服务,以及它们在栈中是如何联系的。同时也分析一下它们的功能,它们提供的服务和与安全性的关系。 3.2Winsock编程原理 通过Winsock可实现点对点或广播通信程序,实际这两者之间的区别不大,编程时其程序流程所用代码几乎相同,不同的地方在于目标地址选择的不同。 由于Winsock的服务是以动态链接库Winsock DLL形式实现的,因此先调用 1、WSAStartup对Winsock DLL进行初始化 2、应用程序关闭套接字后,还应调用WSACleanup终止对Winsock DLL的使用 3.23Winsock编程模型: 流套接字编程模型: 1 .服务器进程创建套接字 socket 2 .将本地地址绑定到所创建的套接字 bind 3 .将套接字置入监听模式并准备接受连接请求 listen,accept 4 .客户进程调用socket函数创建客户端套接字 5 .客户向服务进程发出连接请求 connect 6 .当服务器接收到客户请求,阻塞的accept进程,生成新一个新的套接字与客户套接字建立连接,并向客户端返回接受信号 7 .客户套接字收到服务器接受信号,表示连接建立成功,开始用 send, recv进行收发数据 8 关闭套接字 先用 shutdown 再用 closesocket 数据报套接字编程模型: 服务器用socket创建,用bind绑定 用readfrom从网络上接收,收不到进入阻塞 客户端也用socket , bind绑定 客户端用 sendto发送数据 服务器端接收数据,用sendto进行响应 数据发送完两者调用closesocket进行套接字释放 Winsock I/O模型:阻塞模式:一直等待下去,不会立即返回 非阻塞模式:无论何都会返回关交出程序的控制权 3.3TP工作原理 文件传输协议是从一个系统向另一个系统传递文件的标准方法。它的目标在RFC 0765中写得很清楚。FTP的目标1)促进文件和程序的共享2)鼓励间接和含蓄的使用远程计算机3)使用户不必面对主机间使用的不同的文件存储系统4)有效和可靠地传输文件。FTP,尽管用户可以直接通过终端来使用,是设计成让别的程序使用的。 FTP文件传输应用在客户/服务环境。请求机器启动一个FTP客户端软件。这就给目标文件服务器发出了一个请求。典型地,这个要求被送到端口21。一个连接建立起来后,目标文件服务器必须运行一个FTP服务软件。FTPD是标准的FTP服务daemon。它的功能很简单:回复inetd收到的连接请求,并满足这些要传输文件的请求。这个daemon在许多发行版的UNIX中是个标准。FTPD等待一个连接请求。当这样的一个请求到达时,FTPD请求用户登录。用户提供它的合法的登录名和口令或匿名登录。一旦登录成功,用户可以下载文件了。在某些情况下,如果服务器的安全允许,用户可以上载文件。3.4Winsock API基本函数介绍(1)WSAStartup()函数和WSACleanup()函数 由于Winsock 2提供的API服务是以动态链接库ws2_32.dll实现的,所以必须先调用WSAStartup() 函数对ws2_32.dll进行加载初始化,协商Winsock的版本支持,并分配必要的资源。在应用程序关闭套接字后,还应调用WSACleanup( )函数来终止和卸载动态链接库ws2_32.dll,释放资源。 (2)socket()函数 服务进程和客户进程在通信前必须创建各自的套接字,然后才能用相应的套接字进行发送、接收操作,实现数据的传输。服务进程总是先于客户进程启动,服务进程和客户进程调用socket() 函数创建套接字。 (3)bind( ) 函数 当用socket( )创建套接字后,它便存在于一个名字空间(地址族)中,但并未赋名。bind ( )函数通过给一个未命名套接字分配一个本地名字(主机地址/端口号)来为套接字建立本地捆绑。客户端一般隐式地向操作系统请求一个随机的未使用过的临时端口号,跟自己的IP地址一起,与所创建的套接字建立联系,由于该临时端口号客户端程序事先是不确定的,因此不显式地使用绑定函数。 (4)listen( )函数 调用listen( )函数对服务器上套接字启动监听,即允许客户连接请求开始排队。 (5)accept( )函数 服务器设置监听工作方式后,通过调用 accept( ) 函数使套接字等待接受客户连接。如果已有连接请求到来,该函数会返回一个新的套接字描述符,它对应于已经接受的那个客户端连接。对于该客户机后续的所有操作,都应使用这个新套接字。至于原来那个监听套接字,它仍然用于接受其他客户机连接,继续处于监听模式。 (6)connect( )函数 客户端利用 connect( ) 函数和服务器建立一个端到端的连接。 (7)closesocket( )函数 网络通信任务完成后,利用本函数释放套接字占用的所有资源。4.总体设计4.1了解Winsock与操作系统的关系4.2实现功能流程图5.详细设计5.1文件传输源程序代码(1)客户端client程序代码#include Winsock.h#include windows.h #include stdio.h #include time.h #include #define RECV_PORT 3312 #define SEND_PORT 4302 #pragma comment(lib, wsock32.lib)SOCKET sockclient; char filename20; /文件名 sockaddr_in ServerAddr; /服务器地址 char rbuff1024; /接收缓冲区 char sbuff1024;/发送缓冲区 char InputIP20;/存储输入的服务器IPvoid help() /处理help命令 cout 欢迎进入迷你FTP帮助菜单 endl * * * * * * * * * * * * * * * * * * * * * endl 1.get.下载(接受)文件 endl get的用法: get 文件名 endlendl 2.put.上传(发送)文件 endl put的用法:put 文件名 endl 3.pwd.显示当前文件夹的绝对路径 endl 4.dir.显示远方当前目录的文件 endlendl 5.cd.改变远方当前目录和路径 endl cd的用法(进入下级目录): cd 路径名 endl cd的用法(进入上级目录): cd . endlendl 6.?或者help.进入帮助菜单 endl 7.quit.退出FTP endl * * * * * * * * * * * * * * * * * * * * * endl; /*dir:列出远方当前目录*/void list(SOCKET sockfd) int nRead; while(true) nRead=recv(sockclient,rbuff,1024,0);/recv函数通过sockclient套接口接受数据存入rbuff缓冲区,返回接受到的字节数 if(nRead=SOCKET_ERROR) printf(read response error!n); exit(1); if(nRead=0)/数据读取结束 break; /显示数据 rbuffnRead=0; printf(%s,rbuff); /* put:传给远方一个文件*/int SendFile(SOCKET datatcps,FILE* file) printf( sending file data.); for(;) /从文件中循环读取数据并发送客户端 int r=fread(sbuff,1,1024,file);/fread函数从file文件读取1个1024长度的数据到sbuff,返回成功读取的元素个数 if(send(datatcps,sbuff,r,0)=SOCKET_ERROR) printf(lost the connection to client!n); closesocket(datatcps); return 0; if(r1024) /文件传送结束 break; closesocket(datatcps); printf(donen); return 1; DWORD StartSock() /启动winsock WSADATA WSAData; char a20; memset(a,0,20); if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)/加载winsock版本 printf(sock init fail!n); return (-1); if(strncmp(InputIP,a,20)=0) printf(请输入连接的主机IP:);scanf(%s,&InputIP); /设置地址结构ServerAddr.sin_family=AF_INET;/AF_INET表示使用IP地址族 ServerAddr.sin_addr.s_addr=inet_addr(InputIP);/指定服务器IP ServerAddr.sin_port=htons(RECV_PORT);/设置端口号 return(1); /创建套接字 DWORD CreateSocket() sockclient=socket(AF_INET,SOCK_STREAM,0);/当socket函数成功调用时返回一个新的SOCKET(Socket Descriptor) if(sockclient=SOCKET_ERROR) printf(sockclient create fail! n); WSACleanup(); return(-1); return(1); DWORD CallServer() /发送连接请求 CreateSocket(); if(connect(sockclient,(struct sockaddr*)&ServerAddr,sizeof(ServerAddr) =SOCKET_ERROR) /connect函数创建与指定外部端口的连接 printf(Connect fail n); memset(InputIP,0,20); return(-1); return(1); DWORD TCPSend(char data) /发送命令 int length; length=send(sockclient,data,strlen(data),0); /send函数通过sockclient接口发送data里面的数据,发送成功返回发送的字节数 if(length0) fwrite(rbuff,sizeof(rbuff),count,fd);/把count个数据长度为size0f()的数据从 rbuff输入到fd指向的目标文件 fclose(fd); /关闭文件 if(strncmp(rbuff,put,3)=0) /put strcpy(filename,rbuff+9); fd2=fopen(filename,rb);/rb读写打开一个二进制文件,只允许读写数据。 if(fd2)if(!SendFile(sockclient,fd2) printf(send failed!); return 0; fclose(fd2);/关闭文件 else/打开文件失败 strcpy(sbuff,cant open file!n); if(send(sockclient,sbuff,1024,0) return 0; if(strncmp(rbuff,dir,3)=0) /dir printf(n); list(sockclient);/列出接受到的列表内容 if(strncmp(rbuff,pwd,3)=0) list(sockclient);/列出接受到的内容-绝对路径 if(strncmp(rbuff,cd,2)=0) /cd closesocket(sockclient);/关闭连接WSACleanup();/释放Winsock return main(); (2)、服务器端server程序代码#include Winsock.h #include windows.h #include stdio.h #define RECV_PORT 3312 #define SEND_PORT 4302 #pragma comment(lib, wsock32.lib)SOCKET sockclient,sockserver; sockaddr_in ServerAddr;/服务器地址sockaddr_in ClientAddr;/客户端地址 /*全局变量*/int Addrlen;/地址长度 char filename20;/文件名 char order10;/命令 char rbuff1024;/接收缓冲区 char sbuff1024;/发送缓冲区 DWORD StartSock() /初始化winsock WSADATA WSAData; if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0) printf(socket init fail!n); return (-1); return(1); DWORD CreateSocket() sockclient=socket(AF_INET,SOCK_STREAM,0); if(sockclient=SOCKET_ERROR) printf(sockclient create fail ! n); WSACleanup(); return(-1); ServerAddr.sin_family=AF_INET; ServerAddr.sin_addr.s_addr=htonl(INADDR_ANY); ServerAddr.sin_port=htons(RECV_PORT); if(bind(sockclient,(struct sockaddr FAR *)&ServerAddr,sizeof(ServerAddr)=SOCKET_ERROR) /bind函数将套接字和地址结构绑定 printf(bind is the error); return(-1); return (1); int SendFileRecord(SOCKET datatcps,WIN32_FIND_DATA *pfd) /用来发送当前文件记录 char filerecordMAX_PATH+32; FILETIME ft; /文件建立时间 FileTimeToLocalFileTime(&pfd-ftLastWriteTime,&ft); SYSTEMTIME lastwtime; /SYSTEMTIME系统时间数据结构 FileTimeToSystemTime(&ft,&lastwtime); char *dir=pfd-dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY?: ; sprintf(filerecord,%04d-%02d-%02d %02d:%02d %5s %10d %-20sn, lastwtime.wYear, lastwtime.wMonth, lastwtime.wDay, lastwtime.wHour, lastwtime.wMinute, dir, pfd-nFileSizeLow, pfd-cFileName); if(send(datatcps,filerecord,strlen(filerecord),0)=SOCKET_ERROR) /通过datatcps接口发送filerecord数据,成功返回发送的字节数 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);/可以通过FindFirstFile()函数根据当前的文件存放路径查找该文件来把待操作文件的相关属性读取到WIN32_FIND_DATA结构中去: if(hff=INVALID_HANDLE_VALUE)/发生错误 const char *errstr=cant list files!n; printf(list file error!n); if(send(datatcps,errstr,strlen(errstr),0)=SOCKET_ERROR) printf(error occurs when senging file list!n); closesocket(datatcps); return 0; BOOL fMoreFiles=TRUE; 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(sbuff,1,1024,file);/把file里面的内容读到sbuff缓冲区 if(send(datatcps,sbuff,r,0)=SOCKET_ERROR) printf(lost the connection to client!n); closesocket(datatcps); return 0; if(r1024)/文件传送结束 break; closesocket(datatcps); printf(donen); return 1; /连接 DWORD ConnectProcess() Addrlen=sizeof(sockaddr_in); if(listen(sockclient,5)0) printf(Listen error); return(-1); printf(服务器监听中.n); for(;) sockserver=accept(sockclient,(struct sockaddr FAR *)&ClientAddr,&Addrlen); /accept函数取出连接队列的第一个连接请求,sockclient是处于监听的套接字ClientAddr 是监听的对象地址, /Addrlen是对象地址的长度 for(;) memset(rbuff,0,1024); memset(sbuff,0,1024); if(recv(sockserver,rbuff,1024,0)0)/recv函数返回接受的字节数赋给count fwrite(rbuff,sizeof(char),count,fd);/把count个数据长度为size0f()的数据从rbuff输入
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 冷却塔填料更换作业实施方案
- 机房UPS电源安装施工方案
- 施工电梯基础桩基施工方案
- 软土地基箱梁支架搭设方案
- 砖混结构施工材料管理方案
- 电梯钢丝绳拆换施工方案
- 外墙施工管理方案
- 2026-2031中国过滤器市场发展战略及投资前景预测咨询报告
- 2026-2031中国火锅店连锁经营行业现状研究分析及市场前景预测报告
- 膨胀蛭石回填施工方案及流程
- GB/T 11361-2008同步带传动梯形齿带轮
- 公益事业捐赠预评估表
- 江苏开放大学组织行为学期末复习题
- 监狱消防安全知识讲座课件
- 科学社会学的研究对象
- 工程会议签到表
- 去极端化学习材料课件
- 危废管理台账
- 一级注册计量师《计量专业案例分析》历年试题
- 寿阳经济技术开发区规划(2021-2035年)环境影响评价报告书
- PRS-7177电能质量在线监测说明书
评论
0/150
提交评论