文件传输系统设计文档
1引言
1.1编写目
按照公司布置的实习任务,实现文件传输系统,并完成代码的撰写,在编写代码的过程中,对学过的专业知识进行回顾,加强编写代码的能力和逻辑思维能力,初步掌握C++网络编程原理。在撰写设计文档的过程中,对一个项目的设计开发过程进行梳理,熟悉设计文档编写的规范和要求,为今后项目开发打下坚实的基础。
1.2背景
该项目是在Visual C++的MFC下进行的开发,要求对C++语言熟练的掌握,系统的开发涉及到网络原理的SOCKET编程和操作系统的多线程编程技术。文件传输功能成为现在流行的即时通信工具不可少的一部分。要实现一个功能较完善的文件传输工具,若只能实现文件的发送与接收,显然是不够的。本文开发的文件传输工具,通过使用多线程、自定义的传输命令等技巧,实现了多个用户之间并发传输多个文件,并可以在传输过程进行简单交互的功能。
1.3部分用到的词定义
Socket:通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
CSocket类:是MFC对Windows Socket编程的类的封装,其派生于CAsyncSocket类,即是CAsyncSocket类的更抽象的封装,用该类来完成Socket编程将更方便。
串行化:将对象存储到介质(如文件、内在缓冲区等)中或是以二进制方式通过网络传输。之后可以通过反串行化从这些连续的字节(byte)数据重新构建一个与原始对象状态相同的对象,因此在特定情况下也可以说是得到一个副本,但并不是所有情况都这样。
TCP:Transmission Control Protocol 传输控制协议,是一种面向连接的、可靠的、基于字节流的运输层通信协议。
多线程:为了使得多个线程并行的工作以完成多项任务,以提高系统的效率。线程是在同一时间需要完成多项任务的时候被实现的。
2程序详细设计
2.1程序描述
2.1.1 利用socket进行TCP连接
文件传输系统包括一个服务器端和一个客户端。接收方是TCP的服务器端,发送方是TCP的客户端。
2.1.2 同步的多线程传输方式
要实现并行传输,即服务器端可以同时接收几个客户端发送的文件,我们采用了同步的多线程方式,在程序中有两类线程:接收线程和发送线程,其中监听线程在接收端,发送线程在发送端。
2.1.3发送端与接收端的交互
a.发送端询问接收端,是否同意接收文件以及接收端的应答。
b.在传输过程中发送端取消文件发送。
c.在传输过程中接收方取消文件接收。
2.2功能
1. 文件在传输过程时应不影响用户界面其它的操作;
2. 在正式传输文件前,发送方应先发送请求,接收方可以同意或拒绝文件发送,接收方同意后才能进行传输;
3. 客户端在文件传输过程中,可以显示文件的信息,如文件名,保存路径,文件大小;以及显示传输进度,如完成的百分比,速度;
4. 文件在传输过程中接收方和发送方都可以取消文件传输过程;
5. 可以多个客户端同时向服务器并行发送文件;
6.传输过程中,服务器端和客户端可以进行对话。
l 功能界面图:
图1-1客户端操作界面
图1-2服务器操作界面
l 客户端的用例图:
图1-3 客户端用例图
客户端用例描述:
用例1:连接 |
参与者: 客户端用户 前置条件:1、启动Client.exe 2、设置好正确的IP地址和端口 后置条件:与服务器端建立连接 触发条件:点击“连接” 正常流程:1、创建客户端套接字 2、与服务器建立连接 3、初始化套接字 异常流程:1、IP地址为空,提示“IP地址不能为空” 2、客户端连接套接字创建失败,消息对话框提示 3、客户端连接套接字连接失败,消息对话框提示 4、服务器的问题,消息对话框提示
|
用例2:断开 |
参与者:客户端用户 前置条件:与服务器端连接 后置条件:与服务器端断开连接 触发条件:点击“断开” 正常流程:1、告诉服务器连接被断开 2、关闭客户端套接字 3、弹出消息对话框,“断开” 异常流程: |
用例3:浏览文件 |
参与者:客户端用户 前置条件:启动Client.exe 后置条件:1、显示文件路径 2、显示文件大小 触发条件:点击“浏览文件” 正常流程:1、选择文件 2、获取文件路径,文件名 3、打开文件 4、获取文件大小 5、关闭文件 异常流程: |
用例4:发送 |
参与者:客户端用户 前置条件: 1、已连接到服务器端 2、已经选定文件 后置条件:将文件发送到服务器端 触发条件:点击“发送” 正常流程: 1、向服务器发送文件名和文件大小,请求发送 2、当对方同意且准备好接收文件时,启动文件发送线程 3、发送文件 异常流程: 1、连接的请求被拒绝 2、服务器已经关闭了连接,提示“对方已关闭” 3、发送文件的请求被拒绝,提示 4、对方取消了发送 |
用例5:取消发送 |
参与者:客户端用户 前置条件:文件正在发送中 后置条件:发送过程被取消 触发条件:点击“取消” 正常流程:1、弹出“取消确认”对话框 2、进入扩展用例1
|
用例6:退出 |
参与者:客户端用户 前置条件: client.exe在运行过程中 后置条件:弹出“取消确认”对话框 触发条件:点击“退出” 正常流程:1、弹出“退出确认”对话框 2、进入扩展用例2 异常流程: |
用例7:聊天 |
参与者:客户端用户 前置条件: client.exe在运行过程中 后置条件: 信息发送到服务器端 触发条件: 按回车键,或点击“发送” 正常流程: 1、在“text”上输入信息 2、按回车键,或点击“发送” 异常流程: |
扩展用例1:取消确认 |
参与者:客户端用户 前置条件:点击“取消” 前置条件: 点击“取消” 后置条件: 1、确认取消,停止传输文件,告诉对方发送被取消 2、不取消,则返回继续传输 触发条件:点击“取消确认” 正常流程:若确认取消 异常流程 |
扩展用例2:退出确认 |
参与者: 客户端用户 前置条件: 点击“退出” 后置条件: 1、确认退出,停止传输文件 2、不退出,则返回程序中 触发条件:点击“退出确认” 正常流程:1、如果正在文件传输过程中,弹出信息提示“请先停止传送后再退出” 2、断开连接 3、消除对话框
|
l 服务器端用例图:
图1-4 服务器用例图
服务器用例描述:
用例1:启动 |
参与者: 服务器端用户 前置条件: 运行server.exe 后置条件: 对客户端进行监听 触发条件:点击“启动” 正常流程:1、创建客户端连接字CCListenSocket 2、监听客户端连接 异常流程: |
用例2:关闭 |
参与者: 服务器用户 前置条件:监听客户端 后置条件:关闭服务器套接字 触发条件:点击“关闭” 正常流程:关闭服务器套接字 异常流程: |
用例3:取消 |
参与者:服务器用户 前置条件:文件在传输过程中 后置条件:文件停止传输 触发条件:点击“取消” 正常流程:1、弹出“取消确认”对话框 2、进入扩展用例1 异常流程: |
用例4:退出 |
参与者: 服务器端用户 前置条件:运行server.exe 后置条件:弹出“取消确认”对话框 触发条件:点击“退出” 正常流程:1、弹出“退出确认”对话框 2、进入扩展用例2 异常流程: |
用例5: 聊天 |
参与者: 服务器端用户 前置条件:运行server.exe 后置条件:向服务器端群发消息 触发条件:输入“回车”,或点击“发送” 正常流程:1、在“text”中输入信息 2、输入“回车”,或点击“发送” 异常流程: |
扩展用例1:取消确认 |
参与者: 服务器端用户 前置条件: 点击“取消” 后置条件: 1、确认取消,停止传输文件,告诉对方发送被取消 2、不取消,则返回继续传输 触发条件:点击“取消确认” 正常流程:若确认取消 异常流程: |
扩展用例2: 退出确认 |
参与者:服务器端用户 前置条件: 点击“退出” 后置条件: 1、确认退出,停止传输文件 2、不退出,则返回程序中 触发条件:点击“退出确认” 正常流程: 1、如果正在文件传输过程中,弹出信息提示“请先停止传送后再退出” 2、断开连接 3、消除对话框
异常流程: |
2.3性能
1、可传输大型文件,大于50M
2、客户端在传输大型文件的同时,还可与服务器端进行会话
3、一个服务器端可以接收多个客户端的并发传输
4、多客户端进行并行传输时速度达到每秒1M左右
2.4模块划分
在用例图中已进行分析。
2.5程序系统的结构
这个程序所采用的是基于TCP/IP协议的Winsock编程原理,这种编程模型一般都是采用客户机/服务器(Client/Server)方式,在这个程序里面也正是采用这种基本的方法。
在通信的时候主要可以分为两个部分,一个部分是用于传送控制信息,例如发送文件的请求,文件的名称、大小等,由于这方面的数据量比较小,为了方便起见我采用了MFC所提供的CSocket类的串行化技术来实现;而另一个部分就是文件的传输部分,对于文件的传输,由于数据量相对来说比较大,所以我分别写了两个线程,一个用于发送,一个用于接收。这两个部分在具体实现的时候分别建立有自己的套接字(Socket)。
2.5.1串行化的传输
程序传送控制信息的时候采用的是CSocket类的串行化技术,这样一来使得发送和接收网络数据就像普通的数据串行化一样简单。封装一个可以串行化的消息类,消息的发送和接收只需使用流操作符对缓冲区进行存取就可以了。根据程序的需要,对消息类的CMessage的构造函数进行了重载,CMessage()为默认的构造函数,如果只是发送一般的控制信息我们可以使用CMessage(int nType)构造函数,当需要发送文件名及客户端的编号的时候我们可以使用CMessage(int nType, CString strFileName, DWORD nCount)构造函数,
2.5.2并行的传输
要实现并行传输,即服务器端可以同时接收几个客户端发送的文件,我们采用了同步的多线程方式,在程序中主要有两类线程:_SendThread(发送线程)和_ListenThread(接收线程)。在发送线程中实现了创建客户端套接字,连接服务器端,调用主对话框类中的SendFile成员函数进行文件的发送;在接收线程中实现了创建服务器端套接字,对客户端进行监听,向主对话框发送一个自定义消息WM_ACCEPT_TRANSFERS,发送一个信息告诉发送方可以开始发送文件,接受连接,调用主对话框类中的ReceiveFile成员函数进行文件的接受。
2.5.3 SOCKET类的封装
服务器端:
CListenSocket是负责监听管理的套接字类;CListenSocket(CFileTransfersDlg* pdlgMain)为重载的构造函数;m_pdlgMain为指向主对话框类CServerDlg的指针。重载基类Csocket的OnAccept函数以使对来自客户的连接请求作出响应, 当该套接字接收到客户的连接请求时,就调用CServerDlg对象的ProcessAccept()函数进行处理。
CTransferSocket是负责初始化、传送与接收串行化消息的类,继承于CSocket,参数m_pFile为一个CSocketFile类型的指针用于连接到一个CSocket对象;m_pArchiveIn和m_pArchiveOut均为CArchive类型的指针,分别用于接受和发送。该类重写了CSocket中的OnReceive函数,当有消息在Carchive对象提供的缓冲区中,CTransferSocket自动调用OnReceive函数,用以处理客户端发送过来的消息。Init成员函数用于串行化的初始化,Abort成员函数用于对m_pArchiveOut指针进行释放,SendMsg成员函数用于发送信息,ReceiveMsg成员函数用于接受信息。
CClientSocket作用与服务器端的CTransferSocket类作用基本相同,OnReceive函数实现有所不同。
2.5.4 SOCKET的TCP连接流程图
图2-1 服务器与客户端连接流程图
2.5.5服务器端数据流图
图2-2 服务器端数据流图
2.5.6客户端数据流图
图2-3 客户端数据流图
2.6接口/类具体设计
l 文件传输过程的交互图
图2-4 文件传输交互图
l 类图设计
2.7任务分配
代码部分:
施余主要负责服务器端的开发,张一负责客户端的开发
设计文挡部分:
张一负责整个文档的初稿,施余负责后期的修改
2.8尚未解决的问题
1、传输速率有待进一步提高,可以将一个文件拆分成多个数据包进行多线
程传输。
2、服务器无法定向中止某一个客户端传输文件,只能终止所有客户端的文件传输
2.9 BUG记录
序号 | Bug描述 | 原因 | 解决方法 |
1 | 多个客户端连接服务器后,最后一个连接的客户端可以发送文件,之前连接的客户端无法发送文件 | 服务器端保存的客户 socket为最后一个申请连接的客户端 | 服务器给每个连接的客户端一个编号,并把每个服务器accpet到的客户端socket放入链表 |
2 | 多个客户端连接服务器,服务器无法向所有客户端群发消息 | 原因同序号1 | 循环保存所有客户端socket的链表,向每个socket发送消息 |
3 | 发送聊天消息时,键入“回车”,程序退出
| Enter键默认为确定操作 | 使“发送消息”按钮为默认按钮,按回车键可以发送消息 |
4 | 服务器取消保存时,客户端没有收到发送被拒绝的消息,继续以准备传输的状态等待
| 缺乏一个对服务器没有接收文件的事件的响应 | 1、服务器拒绝接收时,同时向客户端发送一个拒绝接收的信息
|