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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

本文(文件传输协议的C语言实现文档格式.docx)为本站会员(b****2)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

文件传输协议的C语言实现文档格式.docx

1、网络中两台主机各自在自己机器上建立通信的端点-套接字,然后使用套接字进行数据通信。一个套接字包含五个基本元素:协议类型、本地IP地址、本地端口、远端IP地址和远端端口。在操作系统中,套接字是一种系统资源,应用程序使用时应向操作系统申请或注册,使用结束后应用程序应释放该该套接字。和其他系统资源一样,操作系统为套接字分配一个唯一的ID(在Windows中被称作句柄)。根据网络通信的特征,套接字分为三类:流套接字(SOCK_STREAM)、数据报套接字(SOCK_DGRAM)和原始套接字(SOCK_RAW)。流套接字是面向连接的,它提供双向的、有序的、无差错、无重复并且无记录边界的数据流服务,适用于

2、处理大量数据,提供可靠的服务。数据报套接字是无连接的,它支持双向的数据传输,具有开销小、数据传输效率高的特点,但不保证数据传输的可靠性、有序性和无重复性,适合少量数据传输、以及时间敏感的音/视频等多媒体数据传输。原始套接字(SOCK_RAW)可以用作对底层协议(如IP或ICM)的直接访问。Winsock网络应用程序利用API 函数(如accept、send、recv等函数)进行I/O操作时有阻塞和非阻塞两种模式。若要获取的资源还没有到达(如:接收缓冲区中没有数据提供给recv函数),在阻塞模式下,执行I/O操作的Winsock函数在I/O操作完成前会一直等待下去,不会立即返回;而在非阻塞模式下

3、,该函数不管I/O操作有没有完成都会立即返回,若未完成一般会返回错误码WSAWOULDBLOCK,意味着必须重新进行尝试。阻塞模式与非阻塞模式比较,从编程角度来说,前者更便于使用,但从程序运行的效率来说,由于阻塞调用后会使得所在的线程(如果是主线程那么就是整个程序)等待在该I/O操作上,因此后者效率更高。默认情况下,这些I/O操作工作于阻塞模式。在阻塞模式下使用Winsock 2的API库函数进行数据报套接字编程的过程如图ChpNum-2所示。在服务器端,先调用WSASartup函数进行初始化,初始化完成后调用Socket函数创建一个Socket s,再调用bind函数将该套接字绑定到某个特定

4、端口,接下来调用Listen函数启动监听并调用Accept函数接收客户连接,若客户连接请求未及时到达,则Accept函数处于阻塞状态。Accept函数为客户端的连接请求创建一个新的套接字S1,在以后的通信中,服务器利用套接字s1与客户端进行数据双向传输。通信结束时,服务器可以采用Closesocket函数释放套接字,并可调用WSAClearup释放Winsock DLL。客户机是连接的请求的发起者,在创建Socket之后直接通过调用Connect发起连接请求,成功后即可以利用该Socket进行双向通信了。下面对Winsock 2提供的主要接口函数逐一进行介绍。图ChpNum-2 基于TCP的网

5、络应用程序(1)WSAStartup()函数和WSACleanup()函数由于Winsock 2提供的API服务是以动态链接库ws2_32.dll实现的,所以必须先调用WSAStartup() 函数对ws2_32.dll进行加载初始化,协商Winsock的版本支持,并分配必要的资源。在应用程序关闭套接字后,还应调用WSACleanup( )函数来终止和卸载动态链接库ws2_32.dll,释放资源。(2)socket()函数服务进程和客户进程在通信前必须创建各自的套接字,然后才能用相应的套接字进行发送、接收操作,实现数据的传输。服务进程总是先于客户进程启动,服务进程和客户进程调用socket()

6、 函数创建套接字。(3)bind( ) 函数当用socket( )创建套接字后,它便存在于一个名字空间(地址族)中,但并未赋名。bind ( )函数通过给一个未命名套接字分配一个本地名字(主机地址/端口号)来为套接字建立本地捆绑。客户端一般隐式地向操作系统请求一个随机的未使用过的临时端口号,跟自己的IP地址一起,与所创建的套接字建立联系,由于该临时端口号客户端程序事先是不确定的,因此不显式地使用绑定函数。(4)listen( )函数调用listen( )函数对服务器上套接字启动监听,即允许客户连接请求开始排队。(5)accept( )函数服务器设置监听工作方式后,通过调用 accept( )

7、函数使套接字等待接受客户连接。如果已有连接请求到来,该函数会返回一个新的套接字描述符,它对应于已经接受的那个客户端连接。对于该客户机后续的所有操作,都应使用这个新套接字。至于原来那个监听套接字,它仍然用于接受其他客户机连接,继续处于监听模式。(6)connect( )函数客户端利用 connect( ) 函数和服务器建立一个端到端的连接。(7)closesocket( )函数网络通信任务完成后,利用本函数释放套接字占用的所有资源。4 软件设计 本设计客户端及服务器端均采用单线程实现,命令和数据的传输在同一个Socket链接上进行。客户端支持DIR(远端文件夹查询)、GET(文件下载)、PUT(

8、文件上传)、PWD(远端当前路径查询)、CD(远端当前路径设置)、MD(远端文件夹创建)、DEL(远端文件删除)等7个常用FTP命令。用户命令格式为“命令字 路径名/文件名”,如下载当前目录下的test.txt文件,则用户在控制台界面输入的命令格式为“GET test.txt”。客户机和服务器的命令格式约定为“命令字$路径名/文件名”,即test.txt文件下载命令格式为“命令字$路径名/文件名”。图ChpNum-3 程序流程图ChpNum-3(a)示出了客户机的主程序流程,初始化Winsock后,用socket函数新建一个socket,填写入服务器的及IP地址及监听端口后,利用connnec

9、t函数连接到服务器后即提示用户输入ftp命令,程序阻塞在scanf函数。用户输入命令后,scanf函数返回,通过字符串比对函数strncmp识别命令,并调用相应的命令发送函数,若输入的是quit命令,客户端程序退出。命令处理函数主要工作有两个,一是构建命令字节流发送到服务器,二是与服务器交互该命令的后续执行数据,例如,对于get命令,该函数在发出get命令请求字节流后,要接收服务器下发的文件数据。各命令处理函数的实现请参见源代码。图ChpNum-3(b)示出了服务器端主程序流程,先初始化Winsock,建立Socket并绑定到监听端口,启动监听,阻塞在Accept函数等待连接请求的到来,当连接

10、请求到达,Accept函数为该请求创建新的Socket用于与对应的客户通信,而原来Socket继续处于监听状态。此后,主程序从新的Socket中读取命令,通过字串比较识别命令,若发现是quit命令,则关闭当前连接,准备接收下一个连接;若不是quit命令,则转移到相应的命令处理函数,处理完毕后继续在该Socket上读取命令并进行处理。各命令处理函数的设计请参看源代码。5程序代码5.1 服务器端程序文件/*文件名: server.c说明: 简单的ftp服务器端程序文件,包含main函数及get、put等命令处理函数。*/#include winsock2.hstdlib.h#pragma comm

11、ent(lib,ws2_32.lib)WSADATA wsd;char SendBuffer80,RecvBuffer80;/发送缓冲区及接收缓冲区#define DEFAULT_LSTN_PORT 2416 /本地默认监听端口int n,bytes;SOCKET h_NewSocket; /accept函数产生的新socketstruct sockaddr_in RemoteAddr;char path80=;char strObject100=int iSynError=1;int sdirfun(SOCKET h_NewSocket);int sgetfun(SOCKET h_NewSo

12、cket);int sputfun(SOCKET h_NewSocket);int spwdfun(SOCKET h_NewSocket);int scdfun(SOCKET h_NewSocket);int smdfun(SOCKET h_NewSocket);int sdelfun(SOCKET h_NewSocket);/*函数名:main 主函数输入参数: int argc 输入参数长度 char *argv输入参数,用于传入监听端口号*/int main(int argc, char *argv) struct sockaddr_in SLocalAddr; SOCKET h_Soc

13、ket4Lstn; /欲用作监听的socket int addr_in_len;/地址长度 /初始化winsock if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) WSACleanup(); printf(WSAStartup failedn); memset(&SLocalAddr,0,sizeof(SLocalAddr); /创建socket h_Socket4Lstn = socket(PF_INET, SOCK_STREAM, 0); if (h_Socket4Lstn 0) printf(creating socket failedn SLocal

14、Addr.sin_family = AF_INET; if(argc = 2) SLocalAddr.sin_port = htons(u_short)atoi(argv1); else SLocalAddr.sin_port = htons(DEFAULT_LSTN_PORT); SLocalAddr.sin_addr.s_addr = INADDR_ANY; /绑定socket if (bind(h_Socket4Lstn,(struct sockaddr *)(&SLocalAddr),sizeof(SLocalAddr) 0) printf(Bind failed!n while (1

15、) /主循环 listen(h_Socket4Lstn,3); /启动监听 addr_in_len = sizeof(RemoteAddr); /接受连接请求 h_NewSocket = accept( h_Socket4Lstn, (struct sockaddr *) (&RemoteAddr) , &addr_in_len); if (h_NewSocket = INVALID_SOCKET) break;/出错退出%s is connected at port %d n,inet_ntoa(RemoteAddr.sin_addr), ntohs(SLocalAddr.sin_port)

16、; sprintf(SendBuffer,200 Welcome rn /向客户端发送欢迎消息 bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0);530 Log in rn while (1) /接收客户端的命令并调用命令处理函数 n = 0; iSynError=1; bytes = recv(h_NewSocket, &RecvBuffern, 1, 0); if (bytes tmp.txt system(strObject); /system函数执行shell命令 p_FiLeTemp=fopen(,r /打开执行

17、结果文件,准备发送到客户端125 Transfering. rn while (fgets(temp_buffer,80,p_FiLeTemp)!=NULL) /每次读取80字节发送 %s,temp_buffer); / send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); fclose(p_FiLeTemp); /发送完毕,关闭结果临时文件226 Transfer completed. rn system(del tmp.txt /删除结果临时文件226 Close the data socket. rndir command has been done! nsgetfun 用于处理来自客户端的文件下载命令int sgetfun(SOCKET h_NewSocket) int i=4,k=0; char FileName20,temp_buffer80;char *p_FileName=strObject; FILE *fp;required file is: /打印文件名到屏幕 /提取文件名RecvBufferi, 1, 0);%c,RecvBufferi); FileNamek=RecvBufferi; if (RecvBufferi = ) FileNamek = if (RecvBufferi

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2