面向对象大作业讲解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
面向对象作业
指导教师:
院系:控制科学与工程学院
班级:
学号:
姓名:
提交时间:2013-12-22
大连理工大学
Dalian University of Technology
一问题分析
随着计算机网络的不断发展,人们越来越习惯于在网上交流信息,上网聊天已经成为人们日常生活的一部分。使用网上聊天已经成为现代年轻人一种新的交往方式。聊天室更适合于陌生人之间进行较为主观、感兴化的讨论。所以有大部分的人会进入聊天室聊天,它会给人一个完全自由的聊天世界。尤其是针对公司等团体越来越需求一款可以群聊的并且可以发送文件的软件。基于局域网的聊天室可以满足人们发送消息等基本功能,因此,制作一个聊天软件是很重要且非常有意义的。
本设计主要根据作业要求,实现单文档多视图交互、群聊、服务器文件传输、聊天记录的保存、视频播放等功能。
二算法选择
在聊天室设计中,使用的协议主要有TCP(Transmission Control Protocol)、UDP(User Datagram Protocol)。其中TCP提供IP环境下的数据可靠传送,而UDP则不为IP提供可靠性、流控或差错恢复功能。一般来说TCP对应的是可靠性要求高色应用,为UDP则是可靠性要求低传输经济的应用。并且TCP属于面向连接的传输,UDP属于面向非连接的传输。相对来说,虽然TCP编程复杂,需要经过单词“对话”建立起来连接,但是稳定性强,不会出现对数据情况,所以选择TCP协议设计。使用MFC的封装类CSocket进行数据的传送,流程图如图1所示。
图 1 消息发送流程
三方案设计
此系统分为两部分:服务器端和客户端。服务器端用于提供一个网络接口,等待客户端连接及发送请求,登录到洗服务器,然后进行消息的发送;客户端可以通过服务器端的IP地址发送连接请求,登录到聊天系统。聊天系统主要是通过使用各个类来实现相应的功能。
1. 服务器端
三个子窗口类CChatView、CleftView、CSmallView分别用于聊天信息显示、在线用户的显示、文件的发送。通过在主框架中对窗口进行分割成3部分并映射给三个视图类。分割结果如图所示2。
图 2 服务器窗口
几种重要视图类的成员函数或成员变量:
表格 1 视图类
套接字类CClientSocket、CListeningSocket分别用于消息的发送和监听;CMsg用于消息的存储;CPortDlg类用于首次登陆服务器端时IP地址及端口的设置。登录对话框如图3所示。
图 3 端口设置
2. 客户端
四个窗口类CInputView、CLeftView、CMessageView、CSmallView分别用于消息的输入、在线用户的显示、消息记录的显示和文件接收窗口。同样通过在主框架中对窗口进行分割成3部分并映射给三个视图类。分割结果如图所示。
图 4 客户端窗口
客户端窗口类的成员函数及变量如表2所示。
表格 2 客户端视图类
CChatSocket类用于与服务器端连接及消极的接受;CLogonDlg用于与服务器端连接IP 及端口的设计,其需要与服务器端所设置的一致;CMsg类用于消息的存储与表达;CMediaDialog、Cox1、CWM…用于视频播放的窗口的调用和WindowsMediaPlayer控件的使用。其中连接操作如图5所示及视频播放对话框显示如图6所示。
图 5 连接参数
图 6 视频播放对话框
四编程实现
1. 窗口化分
服务器端窗口划分代码的实现:在主窗口MainFrame.cpp中的BOOLCMainFrame:: OnCreateClient(LPCREATESTRUCT /*lpcs*/,CCreateContext* pContext)中应用窗口化分函数CreateStatic()、CreatView()等函数实现窗口的划分。客户端由OnCreateClient()函数实现,具体代码实现为:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
CCreateContext* pContext)
{
if (!m_wndSplitter.CreateStatic(this, 1, 2))
return FALSE;
if (!m_wndSplitter1.CreateStatic(
&m_wndSplitter, 2, 1,
WS_CHILD | WS_VISIBLE | WS_BORDER,
m_wndSplitter.IdFromRowCol(0, 0)
))
{
TRACE0("Failed to create nested splitter\n");
return FALSE;
}
if(!m_wndSplitter1.CreateView(0,0, RUNTIME_CLASS(CLeftView), CSize(100,100), pContext))
{
m_wndSplitter.DestroyWindow();
m_wndSplitter1.DestroyWindow();
return FALSE;
}
if(!m_wndSplitter1.CreateView(1,0, RUNTIME_CLASS(CChatView), CSize(100,100), pContext))
{
m_wndSplitter.DestroyWindow();
m_wndSplitter1.DestroyWindow();
return FALSE;
}
if(!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CSmallView), CSize(100, 100), pContext))
{
m_wndSplitter.DestroyWindow();
return FALSE;
}
m_wndSplitter.SetColumnInfo(0, 450,100);
m_wndSplitter1.SetRowInfo(0, 250, 100);
return TRUE;
return TRUE;
}
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
CCreateContext* pContext)
{
// 创建划分窗口
if (!m_wndSplitter.CreateStatic(this, 2, 2))
return FALSE;
CRect rectClient;
GetClientRect(rectClient);
int nWidth=rectClient.right-rectClient.left;
int nHeight=rectClient.bottom-rectClient.top;
if(!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CMessageView), CSize(nWidth/2.0, nHeight/2.0), pContext))
{
m_wndSplitter.DestroyWindow();
return FALSE;
}
if(!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CInputView), CSize(nWidth/2.0, nHeight/2.0), pContext))
{
m_wndSplitter.DestroyWindow();
return FALSE;
}
if(!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CSmallView), CSize(nWidth/2.0, nHeight/2.0), pContext))