ImageVerifierCode 换一换
格式:DOCX , 页数:27 ,大小:26.81KB ,
资源ID:10817109      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10817109.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(FTP协议解析课程设计报告.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

FTP协议解析课程设计报告.docx

1、FTP协议解析课程设计报告FTP协议实验报告实验目的1、在Linux系统上完成一个文件传输协议(FTP)的简单实现。2、深入理解FTP协议的原理和协议细节。3、学会利用Socket接口设计实现简单应用层协议。4、掌握TCP/IP网络应用程序的基本设计方法和实现技巧。实验原理1、FTP协议FTP是File Transfer Protocol,即文件传输协议的缩写。该协议用于在两台计算机之间传送文件。FTP会话包括了两个通道,一个是控制通道,一个是数据通道。控制通道是和FTP服务器进行沟通的通道,连接FTP服务器,发送FTP指令;数据通道则是和FTP服务器进行文件传输或者获取文件列表的通道。FTP

2、协议中,控制连接的各种指令均由客户端主动发起,而数据连接有两种工作方式:主动方式 (PORT方式)和被动方式(PASV方式)。主动方式下,FTP客户端首先和FTP服务器的控制通道对应端口(一般为21)建立连接,通过控制通道发送命令,客户端需要接收数据的时候在这个通道上发送PORT命令。PORT命令包含了客户端用什么端口(一个大于1024的端口)接收数据。在传输数据的时候,FTP服务器必须和客户端建立一个新的连接,服务器通过自己的TCP 20端口发送数据。被动方式下,建立控制通道的过程和主动方式类似,当客户端通过这个通道 发送PASV命令的时候,FTP server打开一个位于1024-5000

3、之间的随机端口并且通知客户端,然后客户端与服务器之间将通过这个端口进行数据的传送。2、socket编程(1)什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程。网络的 Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。(2)Socket的建立为了建立Socket,程序可以调用Socket函数,该函数返回一个socket描述符。Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上建立一个Socket意味着为一个Socket数据结构分配存储

4、空间。Socket执行体为你管理描述符表。两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。Socket数据结构中包含这五种信息。socket函数原型为:int socket(int domain, int type, int protocol);domain:指明所使用的协议族,通常为PF_INET,表示互联网协议族(TCP/IP协议族);type:指定socket的类型为SOCK_STREAM 或SOCK_DGRAM,Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;protocol:通常赋值0。

5、 返回:整型socket描述符。(3)Socket配置 无连接socket的客户端和服务端以及面向连接socket的服务端通过调用 bind函数来配置本地信息。Bind函数将socket与本机上的一个端口相关联,随后你就可以在该端口监听服务请求。Bind函数原型为: int bind(int sockfd,struct sockaddr_in *my_addr, int addrlen);Sockfd:调用socket函数返回的socket描述符my_addr:一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针addrlen:常被设置为sizeof(struct sockad

6、dr)。struct sockaddr_in结构类型是用来保存socket信息的:struct sockaddr_in short int sin_family; /* 地址族 */ unsigned short int sin_port; /* 端口号 */ struct in_addr sin_addr; /* IP地址 */ unsigned char sin_zero8; /* 填充0 以保持与struct sockaddr同样大小 */;sin_zero:用来将sockaddr_in结构填充到与struct sockaddr同样的长度,可以用bzero()或memset()函数将其置

7、为零。使用bind函数时,可以用下面的赋值实现自动获得本机IP地址和随机获取一个没有被占用的端口号: my_addr.sin_port = 0; /* 系统随机选择一个未被使用的端口号 */ my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */ 通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。同样,通过将my_addr.sin_addr.s_addr置为INADDR_ANY,系统会自动填入本机IP地址。Bind()函数在成功被调用时返回0;出现错误时返回-1并将errno置为相应的错误号。需要注意的是,

8、在调用bind函数时一般不要将端口号置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024中的任何一个没有被占用的端口号。(4)连接建立无连接协议从不建立直接连接。面向连接的服务器也从不启动一个连接,它只是被动的在协议端口监听客户的请求。Listen函数使socket处于被动的监听模式,并为该socket建立一个输入数据队列,将到达的服务请求保存在此队列中,直到程序处理它们。int listen(int sockfd, int backlog);Sockfd: Socket系统调用返回的socket 描述符backlog:指定在请求队列中允许的最大请求数,进入的连接请求将在

9、队列中等待accept()。如果一个服务请求到来时,输入队列已满,该socket将拒绝连接请求,客户将收到一个出错信息。返回:当出现错误时listen函数返回-1,并置相应的errno错误码。accept()函数让服务器接收客户的连接请求。在建立好输入队列后,服务器就调用accept函数,然后睡眠并等待客户的连接请求。 int accept(int sockfd, void *addr, int *addrlen);sockfd:被监听的socket描述符;addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机从某个端口发出该请求);ad

10、drten:通常为一个指向值为sizeof(struct sockaddr_in)的整型指针变量;返回:出现错误时accept函数返回-1并置相应的errno值。(5)结束传输当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:close(sockfd);实验内容在Linux系统上使用Socket接口实现FTP客户端 和服务器的程序,使客户端可以连接至服务器,并且可以进行一些FTP的基本操作,如列出目录、下载文件等。从FTP协议的实现角度来看,客户端 与服务器的命令通道和数据通道需要分享,同时应该支持以下一些FTP命令:get:

11、取远方的一个文件。put:传给远方一个文件。pwd:显示远方当前目录。dir:列出远方当前目录。cd:改变远方当前目录。:显示你提供的命令quit:退出返回实验过程1、实现服务器端(1)全局变量为了记录缓冲区大小、当前目录、当前工作路径、帮助信息而定义了以下几个全局变量: #define dataLen 1024 /缓冲区大小char currentDirPath200; /当前工作目录的绝对路径char currentDirName30; /当前目录的名称char help=get get a file from servernput upload a file to servernpwd

12、display the current directory of serverndir display the files in the current directory of serverncd change the directory of servern? display the whole command which equals helpnquit returnn; /帮助信息(2)函数在服务器端实现了以下几个函数:char *getDirName(char *dirPathName); /根据当前工作目录的绝对路径得到当前目录名称void cmd_pwd(int sock); /

13、处理pwd命令void cmd_dir(int sock); /处理dir命令void cmd_cd(int sock,char *dirName); /处理cd命令void cmd_help(int sock); /处理?命令void cmd_get(int sock,char*fileName); /处理get命令void cmd_put(int sock,char *fileName); /处理put命令(3)主函数的实现:先建立数据通道和命令通道,然后监听,若有客户端连上,则建立一个子进程,先向客户端发送帮助信息,然后根据客户端的命令来调用上述各函数来处理。int main(int a

14、rgc,char *argv) int sock; /服务器用于监听的数据通道 int sockmsg; /服务器用于监听的命令通道 char client_cmd10; /客户端出发的命令 char cmd_arg20; /客户端输入的文件或目录名,用在cd,put,get命令中 struct sockaddr_in server; /服务器数据通道的信息 struct sockaddr_in servermsg; /服务器命令通道的信息 int datasock; /用于通信的数据通道 int msgsock; /用于通信的命令通道 pid_t child; /client子进程sock=

15、socket(AF_INET,SOCK_STREAM,0); /创建用于传数据的套接字 sockmsg=socket(AF_INET,SOCK_STREAM,0); /创建用于传消息的套接字 int opt = 1,opt2 = 1; setsockopt(sock , SOL_SOCKET , SO_REUSEADDR , &opt , sizeof(opt); /实现sock的重用 setsockopt(sockmsg , SOL_SOCKET , SO_REUSEADDR , &opt2 , sizeof(opt2);/实现sockmsg的重用 if (sock 0 | sockmsg

16、0) /socket创建失败 perror(opening stream socket); exit(1); memset(&server,0,sizeof(server); server.sin_family=AF_INET; /设置协议族 server.sin_addr.s_addr=htonl(INADDR_ANY); /监听所有地址 server.sin_port=htons(45000); /端口设为45000 memset(&servermsg,0,sizeof(servermsg); servermsg.sin_family=AF_INET; /设置协议族 servermsg.s

17、in_addr.s_addr=htonl(INADDR_ANY); /监听所有地址 servermsg.sin_port=htons(45001); /端口设为45001 if (bind(sock,(struct sockaddr *) &server,sizeof(server) 0 | bind(sockmsg,(struct sockaddr *) &servermsg,sizeof(servermsg) 0)/连接不成功 perror(binding stream socket); exit(1); int length = sizeof(server); int lengthmsg

18、 = sizeof(servermsg); if (getsockname(sock,(struct sockaddr *) &server,&length) 0 | getsockname(sockmsg,(struct sockaddr *) &servermsg,&lengthmsg) 0)/得到套接字的本地名字 perror(getting socket name); exit(1); printf(Socket port # %d %dn,ntohs(server.sin_port),ntohs(servermsg.sin_port); memset(currentDirPath,0

19、,sizeof(currentDirPath); getcwd(currentDirPath,sizeof(currentDirPath);/将当前工作目录的绝对路径复制到/currentDirPath中 listen(sock,2); /监听数据通道 listen(sockmsg,2); /监听命令通道 while(1) datasock = accept(sock,(struct sockaddr*)0,(int*)0); /与客户端的数据通道连接 msgsock = accept(sockmsg,(struct sockaddr*)0,(int*)0); /与客户端的命令通道连接 if

20、(datasock = -1 | msgsock=-1) perror(accept); else if(child = fork() = -1) /出错 printf(Fork Error!n); if(child = 0) /子进程 printf(connection accepted! new client comingn); write(datasock,help,strlen(help) + 1);loop: memset(client_cmd,0,sizeof(client_cmd); int rval = 0; rval = read(msgsock,client_cmd,siz

21、eof(client_cmd);/读命令 printf(%dn,rval); if(rval = 0;i -) /找到最后一个/号,之后的字符串即为当前工作目录名称 if(dirPathNamei = /) pos=i; break; dirName = (char *)malloc(len - pos + 1); for(i = pos + 1;i = len;i +) dirNamei - pos - 1 = dirPathNamei; return dirName;(5)void cmd_pwd(int sock)的实现:调用getDirName函数来得到当前工作目录名称,然后发到客户端

22、void cmd_pwd(int sock) int len; char *savePointer = getDirName(currentDirPath); /得到当前工作目录名称 strcpy(currentDirName,savePointer); len = strlen(currentDirName) + 1; write(sock,currentDirName,len); /发到客户端(6)void cmd_dir(int sock)的实现:先遍历当前目录下的所有文件及子目录,得到文件及目录数,把该数目发给客户端后,再一次遍历当前目录下的所有文件及子目录,把文件或目录的名称及信息发

23、给客户端。void cmd_dir(int sock) DIR *pdir; char fileInfo50; int i, fcounts = 0, len; struct dirent *pent; int fd; struct stat fileSta; char filePath200; pdir = opendir(currentDirPath); while(pent = readdir(pdir)!= NULL) /计算文件及目录数 fcounts +; write(sock,&fcounts,sizeof(int); closedir(pdir); if(fcounts = 0) return; else pdir=opendir(currentDirPath); for(i = 0; i d_name;

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1