网络程序设计实验报告实验名称:winsock 编程接口实验实验类型:设计型指导教师:贾浩专业班级:信安1204姓名:马灿学号:20123252电子邮件:实验地点:东6 E307实验日期:实验成绩:__________________________实验七网络程序设计综合实验摘要:本课程设计包含了文件传输协议的简单设计与实现。
文件传送协议是一种最基本的应用层协议按照客户/服务器的模式进行工作,提供交互式的访问,是INTERNET使用最广泛的协议之一。
文件传输协议的简单设计与实现建立在计算机网络实验环境TCP/IP网络体系结构之上,使用socket编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c),利用了已有网络环境设计并实现简单应用层协议。
本设计包括了具体设计任务,基本思路及所涉及的相关理论,设计流程图,调试过程中出现的问题及相应解决办法,实验运行结果,核心程序,个人体会及建议等。
关键词:SOCKET编程,FTPclient/server程序一.问题描述及设计思路1.1 问题描述服务器端:1.指定一个目录作为FTP目录(之后所有的文件操作均在此目录下进行)2.接收客户端的命令请求并提供相应的服务。
客户端:完成与FTP用户的人机界面,以命令的方式向服务器请求服务,主要的命令有:1.CONNECTIP地址端口号2.指定FTP服务器的IP地址和端口号,连接到服务器。
响应:连接成功/失败。
3.LOGIN用户名4.用户登录(假设在服务器端有用户管理功能)5.响应:若用户不存在,提示“无此用户”;若用户存在,提示“密码:”;用户输入密码后,若正确提示“登录成功”;若不成功,提示“密码错误”。
6.3.DIR7.显示FTP服务器的FTP目录的文件列表(假设无子目录)8.响应:目录列表(只要文件名即可)。
9.4.GET文件名10.将FTP目录下的文件下载到本地,支持断点续传11.响应:传送成功/失败/无此文件。
12.5.PUT文件名13.将本地文件上传到FTP目录,支持断点续传14.响应:传送成功/失败/无此文件。
15.6.HELP(客户端和服务器端均有该功能)16.实验环境本次实验采用MFC工程工程采用MFC对话框界面工程名称为MyServer和FTPSOCKET。
17.详细设计过程1.2 设计思路1. FTP协议基础FTP 是TCP/IP 协议组中的协议之一,该协议是Internet文件传送的基础,它由一系列规格说明文档组成。
目标是提高文件的共享性,提供非直接使用远程计算机,使存储介质对用户透明和可靠高效地传送数据。
简单的说,FTP就是完成两台计算机之间的拷贝,从远程计算机拷贝文件至自己的计算机上或从自己计算机中拷贝至远程计算机上。
在TCP/IP协议中FTP标准命令TCP端口号为21,Port方式数据端口为20。
2. 网络文件传输原理在通信的时候主要可以分为两个部分。
一个部分是用于传送控制信息,例如发送文件的请求文件的名称、大小等。
采用MFC所提供的CSocket类的串行化技术来实现,而另一个部分就是文件的传输部分。
对于文件的传输,由于数据量相对来说比较大,使用两个线程。
一个用于发送,一个用于接收。
这两个部分在具体实现的时候分别建立有自己的套接字。
FTP编程基础3. FTP传输原理FTP协议使用两条单独的TCP连接一条专用于发送FTP命令另一条则专用于传递数据。
初始建立连接时服务器在21号端口上接收来自客户端的命令连接。
当需要传送数据时文件列表、文件数据等客户端向服务器发出Port 命令并进入监听状态等待来自服务器的数据连接请求。
总体功能模块图服务器端功能说明:线程控制:线程类别:选择线程类别,单线程或多线程传送文件线程数设置:若选择多线程,可自行设置线程数目,若选择单线程,则默认线程数目为1②启动服务器:设置好线程控制后,点击“启动”按钮启动服务器端③选取文件:选择要发送给客户端的文件④发送文件:获取要发送文件属性:获取到要传送给客户端的文件的基本属性,包括:文件名,大小(B),已发送多少(B),文件路径发送进度显示:显示给客户端发送文件的进度⑤ChatWithServer:启动采用UDP协议的简单聊天系统,用来与客户端进行通讯(客户端和服务器端都得启动,否则无法收到)⑥Help:显示服务器端使用说明客户端功能说明:握手服务器:输入服务器端IP地址,点击“握手服务器”按钮,获取服务器端启动的线程数②连接服务器:与服务器进行连接③接收文件:获取接收文件属性:获取到要接收的服务器端传来的文件的基本属性,包括:文件名,大小(B),已接收多少(B),文件存储路径接收进度显示:显示已接收文件的进度④ChatWithServer:启动采用UDP协议的简单聊天系统,用来与客户端进行通讯(客户端和服务器端都得启动,否则无法收到)⑤获取IP地址:获取本机的主机名及IP地址⑥HELP:显示客户端使用说明2、系统结构3、主要功能流程图(1)文件传输流程图2、用例描述(1)文件传送用例描述二.功能实现及主要代码服务器端启动服务,端口号为8888客户端连接服务,服务器的ip地址为111.9.118.115添加用户上传文件2.txt,上传到C盘刷新服务器,c盘中有2.txt,上传成功添加文件下载文件文件下载到E盘三实验总结通过这次实验,我很好的了解到了文件传输的流程,了解到文件传输协议使得主机间可以共享文件。
FTP 使用TCP生成一个虚拟连接用于控制信息,然后再生成一个单独的TCP 连接用于数据传输。
控制连接使用类似TELNET协议在主机间交换命令和消息。
文件传输协议是TCP/IP网络上两台计算机传送文件的协议,FTP是在TCP/IP网络和INTERNET上最早使用的协议之一,它属于网络协议组的应用层。
FTP客户机可以给服务器发出命令来下载文件,上传文件,创建或改变服务器上的目录。
对套接字的使用和通信模型通信机制有了进一步了解,也熟练的掌握了如何选择通信模型。
对各个函数的使用也有了进一步了解。
四附录代码:服务器初始化套接字BOOL CFTPServerDlg::InitSocket(){if(m_sock == INVALID_SOCKET){m_sock = socket(AF_INET,SOCK_STREAM ,0);}if(INVALID_SOCKET == m_sock){MessageBox("创建套接字失败!");return FALSE;}CString sPort;GetDlgItem(IDC_EDIT_PORT)->GetWindowText(sPort);MessageBox("开启的端口:"+sPort);int nPort = atoi(sPort);if(nPort < 1 || nPort > 65535){MessageBox("端口号错误!");return FALSE;}SOCKADDR_IN srvAddr;srvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);srvAddr.sin_family = AF_INET;srvAddr.sin_port = htons(nPort);if(bind(m_sock,(SOCKADDR*)&srvAddr,sizeof(SOCKADDR))== SOCKET_ERROR){closesocket(m_sock);MessageBox("绑定套接字失败!");return FALSE;}return TRUE;}FileInfo file[10];int count = 0;CString str[10];使用异步选择模型HCURSOR CFTPServerDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}//-----------------------------启动服务----------------------//void CFTPServerDlg::OnStart(){//进入监听状态InitSocket();// 设置socket为窗口通知消息类型// 进入监听模式int m_nClient = listen(m_sock,5);if(m_nClient != 0){MessageBox("Listen error!");closesocket(m_sock);return ;}// MessageBox("Listen success!");//注册网络注册网络异步事件,m_hWnd为应用程序的主对话框或主窗口的句柄if(::WSAAsyncSelect(m_sock, m_hWnd, WM_SOCKET,FD_ACCEPT|FD_CLOSE|FD_READ|FD_WRITE)==SOCKET_ERROR) {MessageBox("WSAAsyncSelect fail!");}else{MessageBox("WSAAsyncSelect success!");}客户端连接服务void CFTPClientDlg::OnConnect(){//先获得IP控件的值BYTE nField0,nField1,nField2,nField3;m_IP.GetAddress(nField0, nField1,nField2, nField3);char buff[20];wsprintf(buff,"%d.%d.%d.%d",nField0,nField1,nField2,nField3);MessageBox(buff);//获取端口号的值int port = atoi(m_port);m_sock = socket(AF_INET,SOCK_STREAM ,0);if(INVALID_SOCKET == m_sock){// MessageBox("创建套接字失败!");return ;}// else// MessageBox("创建套接字成功!");SOCKADDR_IN srvAddr;srvAddr.sin_addr.S_un.S_addr = inet_addr(buff);srvAddr.sin_family = AF_INET;srvAddr.sin_port = htons(port);// srvAddr.sin_port = htons(8888);if(::connect(m_sock, (sockaddr*)&srvAddr, sizeof(srvAddr)) == -1) {MessageBox("连接失败");return ;}elseMessageBox("连接服务器成功");UpdateList();}上传文件//-----------------------上传文件到服务器--------------------------//void CFTPClientDlg::OnPutFile(){/* if(!UserVerfify()){MessageBox("该用户不存在");return ;}*/CFileDialog fileDlg(TRUE,NULL,NULL);if(fileDlg.DoModal() == IDCANCEL)return;CString fileName,filePath; //文件名文件路径CString fileType; //文件类型int fileLength;filePath = fileDlg.GetPathName();CFile newFile;newFile.Open(filePath, CFile::modeRead|CFile::modeReadWrite );//获取文件的名字,大小,路径fileName = newFile.GetFileName();fileName += "#"; //为了区别文件名和传输的内容fileLength = newFile.GetLength();// char *pbuf = new char[1024]; //pbuf存储文件内容// memset(pbuf,0,1024);char *pbuf = new char[MAXSIZE]; //pbuf存储文件内容memset(pbuf,0,MAXSIZE);// char pbuf[1024] = {0};// UINT nBytesRead = newFile.Read( pbuf, fileLength);UINT nBytesRead = newFile.Read( pbuf, MAXSIZE);//-------------用数字1表示上传文件名的识别码---------//// fileName = "1" + fileName;CString pbuf1;pbuf1.Format(pbuf);fileName = "1" + fileName + pbuf;// char* fName1 = (LPSTR)(LPCTSTR)fileName;// strcat(fName1,pbuf);///////////////////////此语句有问题///////////////////////////// MessageBox(fileName);// MessageBox(fName1);newFile.Close();if(nBytesRead >0){// if(send(m_sock,fName1,strlen(fName1)+1,0)==SOCKET_ERROR )if(send(m_sock,fileName,strlen(fileName)+1,0)==SOCKET_ERROR )return;}}下载文件列表void CFTPClientDlg::OnDblclkFileList(NMHDR* pNMHDR, LRESULT* pResult){// TODO: Add your control notification handler code hereint m_count = m_fileList.GetItemCount();if(m_count <=0){MessageBox("没有可以下载的文件列表!");return ;}用户验证BOOL CFTPClientDlg::UserVerfify(){return TRUE;}void CFTPClientDlg::OnButtonUser(){// TODO: Add your control notification handler code hereCString user;GetDlgItem(IDC_EDIT_USERNAME)->GetWindowText(user);user = "4" + user;char* p = (LPSTR)(LPCTSTR)user;MessageBox(user);if(send(m_sock,p,1024,0) ==SOCKET_ERROR){MessageBox("发送失败");return ;}char u[1024] = {0};if(recv(m_sock,u,1024,0) == SOCKET_ERROR){MessageBox("接受数据失败");return ;}MessageBox(u);if( u[0] == 'T')MessageBox("用户验证成功");if( u[0] == 'F'){MessageBox("用户验证失败");m_sock = INVALID_SOCKET;}}。