局域网文件传输实验报告.doc_第1页
局域网文件传输实验报告.doc_第2页
局域网文件传输实验报告.doc_第3页
局域网文件传输实验报告.doc_第4页
局域网文件传输实验报告.doc_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

“TCP/IP协议及网络编程技术”课程实验报告 第19页,共19页局域网文件传输实验报告实验名称:编写局域网内进行文件传输的小工具 实验目的: 通过编写局域网内文件传输的工具,熟悉基于UDP的Socket编程,熟悉Winsock的相关内容。对套接字编程有一定的理解和应用。实验内容: 本小组最终结果实现的实验内容: 完成基本任务要求:输入对方 IP 地址,对方如果存在,可以给对方发送文件。完成扩展任务要求:1 工具具有图形交互界面;2 局域网内使用该工具的两台主机可以互相进行文字通信;3 自动按照一定频率扫描局域网内其他开启了该工具的主机, 并在界面上用列表显示出来;4 传输文件和文字内容时,直接选择界面上已经显示出来的存活主机,不需要手动输入IP 地址。实验准备说明: 操作系统:Windows XP 开发语言:C+,MFC 开发平台:Microsoft Visual C+ 6.0 由于开发图形界面时需要用到MFC,因此对缺乏MFC编译运行环境的VC6可能需要加载相应的动态链接库DLL文件。 加载方法:将DLL文件置放于系统链接库路径。即:C:WINDOWSsystem32 实验设计与开发: 程序设计思路:程序所采用基于TCP/IP协议的Winsock编程原理,编程模型采用客户机/服务器(Client/Server)方式,为了方便使用,设计将客户机和服务器合而为一。 在通信的时候主要可以分为两个部分,一个部分是用于传送控制信息,例如发送文件的请求,文件的名称、大小等,由于这方面的数据量比较小,为了方便起见采用了MFC所提供的CSocket类的串行化技术来实现;而另一个部分就是文件的传输部分,对于文件的传输,由于数据量相对来说比较大,所以分别写了两个线程,一个用于发送,一个用于接收。在添加附加功能聊天时,将聊天相关内容作为小文件传输,并将其显示在相应的控件中。这两个部分在具体实现的时候分别建立有自己的套接字(Socket)。 程序代码内容大体分为图形界面和后台交互两个模块,在最开始设计开发时原本准备以此作为分工,但实际图形界面代码较少,而且主要的复杂点在于事件响应和句柄绑定,比较容易解决,总体工作量较少,因此图形界面后来是共同讨论开发,设计完成后根据具体的控件响应分工相关联的后台交互代码开发。 1.图形界面: 程序采用单一界面工作模式,因此所有代码都集中于以FileTransfersDlg命名的.h和.cpp文件中。这样设计在一定程度上改善后期调试的复杂度。由于需要实现附加功能,最后图形界面所用控件较多,并且每个控件都有响应的消息映射,统计内容,整理如下表: 表1 控件响应消息映射表控件ID关联函数功能描述IDC_RADIO_SERVEROnRadioServer()服务端设置IDC_RADIO_CLIENTOnRadioClient()客服端设置IDC_BEGINOnBegin()服务端为启动功能,客服端为连接功能IDC_DISCONNECTOnDisconnect()服务端为关闭功能,客服端为断开功能IDC_SELECT_FILEOnSelectFile()选择文件IDC_STOP_TRANSFERSOnStopTransfers停止传输IDC_TRANSFILE_RATIOOnTransfileRatio文件传输模式IDC_CHAT_RATIOOnChatRatio聊天模式IDC_SEND_MESSAGEOnSendMessage()发送聊天信息IDC_ALLIP_ONLINEOnSelchangeAllipOnline()获取在线服务器IDCANCELOnCancel()退出程序 另外还有些用于显示相关内容的控件,这里不再列举。2.后台交互:2.1.主要线程 后台交互代码主要为相应控件的响应函数和线程函数。所有代码中涉及了4个线程:_ScanReceiveThread,_ScanDelieveThread,_ListenThread,_SendThread。具体功能列表如下:线程名功能_ScanDelieveThread作为服务端时按一定时间间隔重复发送局域网广播包,为客户端提供在线服务端IP地址_ScanReceiveThread作为客户端时重复监听局域网广播包,获得在线服务端IP地址_ListenThread接收点对点文件线程,重复监听获取并接收获取文件(聊天)信息链接_SendThread发送点对点文件线程,当需要发送文件(聊天)信息时开启_ScanDelieveThread和_ScanReceiveThread为广播包套接字,核心在于设置套接字地址格式。核心代码如下:_ScanDelieveThread:SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0); /初始化套接字,注意格式SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_BROADCAST); /设置广播地址addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8000); /设置端口BOOL bOpt = TRUE; setsockopt(sockClient, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt);/设置套接字格式,尤其是第三个参数:SO_BROADCASTZeroMemory(addrSrv.sin_zero,sizeof(addrSrv.sin_zero);bind(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR);/为套接字绑定固定的IP地址和端口,此处IP地址为广播地址:255.255.255.255sendto(sockClient,sldkfjslfjslksdjfsdl,20,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR);/发送套接字,“sldkfjslfjslksdjfsdl”为发送消息,第五个参数比较重要closesocket(sockClient);/关闭套接字,此处比较重要,尤其是while(1)循环中_ScanReceiveThread:char Buf100; /接收广播包char数组SOCKADDR_IN saRemote; /接收广播包地址INT nFrmSize = sizeof(saRemote); /地址大小,固定SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0); /初始化套接字SOCKADDR_IN addrSrv; /套接字地址WORD Port; /接收端口格式addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); /设置接收套接地址格式,此处为局域网内任意地址addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8000); /套接字端口,此处应该和_ScanDelieveThread中套接字端口相同ZeroMemory(addrSrv.sin_zero,sizeof(addrSrv.sin_zero);bind(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR); /绑定IP地址和端口memset(Buf,0,sizeof(Buf);int nErrCode = recvfrom(sockClient, Buf, 100, 0, (SOCKADDR *)(&saRemote), &nFrmSize);/接收广播包数据,其中Buf接收信息,saRemote接收源地址的IP地址及端口信息,此处实际代码应该根据nErrCode有效性进行判断Port = ntohs(saRemote.sin_port); /得出源地址端口信息Cstring IP = inet_ntoa(saRemote.sin_addr); /得出源地址IP地址由于此处_ScanReceiveThread和_ScanDelieveThread两个进程一直处于激活状态,所以应该设置while(1)或for(;)循环,而且_ScanDelieveThread应该对所得到的IP地址进行处理,代码中进入函数ScanOnlineIp(char *ipAddress)。ScanOnlineIp(char *ipAddress)功能有两个主要功能:判断当前广播包地址是否为本机地址,判断当前广播地址是否已添加。具体代码通过设置一个vertor OnlineIp处理,代码流程如下:if (conventIP != localIP) /判断是否为本机地址 if (OnlineIp.empty() /vector 为空,当前无IP地址,添加操作 else for (int ix=0;ix!=OnlineIp.size();+ix) /循环遍历vector 值 if (conventIP=OnlineIpix) /相等说明改地址已经添加,设置标签 exist =TRUE; if (!exist) /如果标签为假,执行IP地址添加操作 而_ListenThread和_SendThread属于固定IP地址套接字。核心代码如下:_ListenThread:CSocket sockSrvr; if(!sockSrvr.Create(pDlg-m_wPort + PORT) /创建套接字if(!sockSrvr.Listen() /开始监听CSocket recSo;if(!sockSrvr.Accept(recSo) /接收连接sockSrvr.Close(); /关闭套接字 _SendThread:/创建套接字 CSocket sockClient;if(!sockClient.Create() /创建套接字 CString strIPAddress;UINT nPort;pDlg-m_psockClient-GetPeerName(strIPAddress, nPort);/连接到服务器端 if(!sockClient.Connect(strIPAddress, pDlg-m_wPort + PORT) /调用主对话框类中的SendFile成员函数进行文件的发送pDlg-SendFile(sockClient);2.2辅助类:2.2.1 CMessage类:上文说过程序传送控制信息的时候采用的是CSocket类的串行化技术,这样发送和接收网络数据就像普通的数据串行化一样简单。因此封装一个可以串行化的消息类是必要的,因此设计了这个类,后面消息的发送和接收只需使用流操作符对缓冲区进行存取就可以了。根据程序的需要,消息类CMessage的定义如下:class CMessage : public CObjectpublic:void Serialize(CArchive& ar);CMessage();CMessage(int nType);CMessage(int nType, CString strFileName, DWORD dwFileSize);virtual CMessage();public:int m_nType;CString m_strFileName;DWORD m_dwFileSize; 其中,m_nType用于标识消息的类型;m_strFileName为文件的名称;m_dwFileSize为文件的大小。为了方便使用,对消息类的CMessage的构造函数进行了重载,CMessage()为默认的构造函数,如果只是发送一般的控制信息可以使用CMessage(int nType)构造函数,当需要发送文件名及大小的时候可以使用CMessage(int nType, CString strFileName, DWORD dwFileSize)构造函数。2.2.2. CListenSocket类该类主要负责监听管理的套接字。定义如下:class CClientSocket : public CSocketpublic:CClientSocket();virtual CClientSocket();CSocketFile* m_pFile;CArchive* m_pArchiveIn;CArchive* m_pArchiveOut;void Init();void Abort();BOOL SendMsg(CMessage* pMsg);void ReceiveMsg(CMessage* pMsg);CClientSocket(CFileTransfersDlg* pdlgMain); /为重载的构造函数;m_pdlgMain为指向主对话框类CFileTransfersDlg的指针。public:virtual void OnReceive(int nErrorCode);/ Implementationprotected:CFileTransfersDlg* m_pdlgMain;2.2.3 CClientSocket类该类用于连接的管理,其创建的方法与CListenSocket相似。定义略。2.3 自定义消息 自定义一个消息WM_ACCEPT_TRANSFERS,用于当文件接收方同意接收文件且文件接收线程_ListenThread已经准备好接收文件是,发送一个信息给文件发送方,说可以开始发送文件。第一步,需要在主窗口类CFileTransfersDlg的实现文件FileTransfersDlg.cpp的首部加入一句:#define WM_ACCEPT_TRANSFERS WM_USER + 100,定义一个宏。 第二步,实现消息处理函数。该函数使用WPRAM和LPARAM参数并返回LPESULT,其实现如下:LRESULT CFileTransfersDlg:OnAcceptTransfers(WPARAM wParam, LPARAM lParam)/告诉对方文件请求被接受且准备好接收 CMessage* pMsg = new CMessage(ACCEPT);m_psockClient-SendMsg(pMsg);/设置一个ID为2的超时几时器 m_nTimer = SetTimer(2, 5000, NULL);return 0; 第三步,在CFileTransfersDlg类定义中的AFX_MSG块中说明消息处理函数,详见类的定义。 第四步,在FileTransfersDlg.cpp文件的在用户类的消息块中,使用ON_MESSAGE宏指令将消息映射到消息处理函数中,加入了如下一句:BEGIN_MESSAGE_MAP(CFileTransfersDlg, CDialog)/AFX_MSG_MAP(CFileTransfersDlg).ON_MESSAGE(WM_ACCEPT_TRANSFERS, OnAcceptTransfers)/AFX_MSG_MAPEND_MESSAGE_MAP()2.4主要成员函数 这里由于相关重要的成员函数代码较长,不便于在报告中展示。这里只罗列相关函数名和其具体功能。见下表:函数名具体功能GetLocalHostInfo (CString &strHostName, CString &strIPAddress)获得本机IP地址函数,在初始化显示本机IP地址和获得在线IP地址时调用。GetError(DWORD error)获取错误信息,捕获所用错误信息TransfersFailed()传输启动错误处理函数ProcessAccept() CListenSocket套接字类接收到连接请求时 的函数保证服务器端一次只能同一个客户端 存在连接ProcessReceive(CClientSocket* pSocket)CClientSocket套接字类收到信息时的处理函数SendFile(CSocket &senSo)发送文件函数,该函数在发送文件线程被调用ReceiveFile(CSocket &recSo)文件接收函数,该函数在文件接收线程中被调用 具体的控件响应函数此处不再重复罗列。启动程序,生成Dlg主界面2.5 程序流程选择作为服务端/客户端 选择操作1 客户端 服务端启动,等待客户端连接退出 连接成功关闭退出选择操作2选择操作2选择好在线IP,连接 连接成功选择操作3选择通讯模式,聊天/文件传输断开连接,可以进行选择操作1,2文件传输,发送时选择文件,接收时选择存放路径聊天,写好信息点击发送继续相关操作,或者选择操作3 程序界面及运行结果:1. 主界面:文件传输进度条文件信息界面聊天信息发送按钮聊天信息输入界面聊天信息显示界面通讯模式选择界面地址设置界面,右上显示本机地址或选择连接地址服务器/客户端功能操作界面服务器/客户端选择操作界面2. 测试过程开启局域网三台机器,IP地址分别为10.61.0.75,10.61.0.76,10.61.0.77。测试内容1:设置两台服务器,一台客户端,客户端分别根据扫描IP地址跟两台服务器连接。检验是否能够扫描所有在线服务器IP,是否能够正常连接。服务器IP为10.61.0.75和10.61.0.77,客户端IP为10.61.0.76。 测试操作:在三台机器上分别启动程序,选择服务器或客户端。服务器端直接点击“启动”工作,客户端点击Combobox选择在线IP后,点击“连接”。 测试结果:1. 客户端扫描在线IP:结果分析:Combobox下拉显示内容为两台服务器IP,IP地址控件显示本机IP地址。测试正确。2. 选择服务器IP地址,进行连接:测试结果:结果分析:选择服务器10.61.0.75后,IP地址显示当前选中IP,点击连接后,连接按钮变灰,断开按钮变亮。测试正确。3 断开当前服务器,重新连接其他服务器:测试结果: 结果分析:以上两幅结果图,第一图显示内容为断开和10.61.0.75服务器连接,第二图显示内容为成功连接10.61.0.77服务器。 测试内容2:设置两台客户端,一台服务端,检验服务器是否进行单一连接。客户端IP为10.61.0.75和10.61.0.77,服务器IP为10.61.0.76。测试操作:在三台机器上分别启动程序,选择服务器或客户端。服务器端直接点击“启动”工作,客户端10.61.0.75点击Combobox选择服务器端IP后,点击“连接”。接着客户端10.61.0.77重复客户端10.61.0.75操作,查看结果。然后客户端10.61.0.75点击“断开”后客户端10.61.0.77重复刚才操作查看结果。测试结果:10.61.0.75先连: 10.61.0.77后连:10.61.0.75断开连接后10.61.0.77再连:结果分析:假设正确,一台服务器只能跟一台客户端进行连接。测试内容3:测试服务端和客户端聊天功能。服务端IP为10.61.0.76,客户端IP为10.61.0.77。测试操作:接测试内容2服务端和客户端正常连接后,服务端和客户端都选择聊天模式。输入聊天信息,点击发送。查看结果。测试结果:结果分析:以上为四幅按时间顺序执行的结果图:图1表示选择聊天模式后,聊天信息输入文本框及发送按钮变亮,图2表示服务端在文本端输入信息,未点击发送图3表示点击发送后,服务端聊天信息输入文本框清空,聊天信息显示框显示刚刚发送的内容,图4表示客户端对服务端聊天信息的回应。由于服务端和客户端显示内容一样,这里不再重复。测试结果表示功能正常。 测试内容4:测试服务端和客户端聊天功能。服务端IP为10.61.0.76,客户端IP为10.61.0.77。测试操作:接测试内容3服务端和客户端正常连接后,服务端和客户端都选择文件传输模式。服务端点击“选择文件”,选择好文件后,等待对方接受,客户端选择好保存路径后,开始文件传输。测试结果如下: 文件传输方(服务端)测试结果:文件接收方(客户端)测试结果:结果分析:以上总过6幅图也是按各自的时间顺序得出。总体时间顺序流程如下:图1:表示服务端点击“选择文件”后聊天响应控件变灰,但响应内容依然存在。图2:表示服务端选择文件。传输文件为“使用MFC实现点对点的文件传输”。图4:表示客户端选择文件保存路径,路径为“桌面”。图3,图5:分别表示服务端,客户端成功接收文件。图6:表示客户端桌面显示相应文件图标。遇到的问题以及解决方法: 由于

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论