面向对象大作业.docx
- 文档编号:8491339
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:15
- 大小:579.56KB
面向对象大作业.docx
《面向对象大作业.docx》由会员分享,可在线阅读,更多相关《面向对象大作业.docx(15页珍藏版)》请在冰豆网上搜索。
面向对象大作业
面向对象作业
指导教师:
院系:
控制科学与工程学院
班级:
学号:
姓名:
提交时间:
2013-12-22
大连理工大学
DalianUniversityofTechnology
一问题分析
随着计算机网络的不断发展,人们越来越习惯于在网上交流信息,上网聊天已经成为人们日常生活的一部分。
使用网上聊天已经成为现代年轻人一种新的交往方式。
聊天室更适合于陌生人之间进行较为主观、感兴化的讨论。
所以有大部分的人会进入聊天室聊天,它会给人一个完全自由的聊天世界。
尤其是针对公司等团体越来越需求一款可以群聊的并且可以发送文件的软件。
基于局域网的聊天室可以满足人们发送消息等基本功能,因此,制作一个聊天软件是很重要且非常有意义的。
本设计主要根据作业要求,实现单文档多视图交互、群聊、服务器文件传输、聊天记录的保存、视频播放等功能。
二算法选择
在聊天室设计中,使用的协议主要有TCP(TransmissionControlProtocol)、UDP(UserDatagramProtocol)。
其中TCP提供IP环境下的数据可靠传送,而UDP则不为IP提供可靠性、流控或差错恢复功能。
一般来说TCP对应的是可靠性要求高色应用,为UDP则是可靠性要求低传输经济的应用。
并且TCP属于面向连接的传输,UDP属于面向非连接的传输。
相对来说,虽然TCP编程复杂,需要经过单词“对话”建立起来连接,但是稳定性强,不会出现对数据情况,所以选择TCP协议设计。
使用MFC的封装类CSocket进行数据的传送,流程图如图1所示。
图1消息发送流程
三方案设计
此系统分为两部分:
服务器端和客户端。
服务器端用于提供一个网络接口,等待客户端连接及发送请求,登录到洗服务器,然后进行消息的发送;客户端可以通过服务器端的IP地址发送连接请求,登录到聊天系统。
聊天系统主要是通过使用各个类来实现相应的功能。
1.服务器端
三个子窗口类CChatView、CleftView、CSmallView分别用于聊天信息显示、在线用户的显示、文件的发送。
通过在主框架中对窗口进行分割成3部分并映射给三个视图类。
分割结果如图所示2。
图2服务器窗口
几种重要视图类的成员函数或成员变量:
表格1视图类
类名
成员函数或变量
作用
CChatView
voidCChatView
OnInitialUpdate()
创建控件与窗口进行绑定
voidCChatView
message(LPCTSTRlpszMessage)
将消息显示到对应窗口
CEdit
m_EditBox;
编辑控件变量
CLeftView
voidCLeftView
OnInitialUpdate()
初始化视图
voidCLeftView
DeleteChatter(CStringsNickName)
删除退出的用户
CSmallView
voidCSmallView
SendFile(LPCTSTRstrFilename)
发送文件
voidCSmallView
OnBnClickedCheck1()
监听客户端
CSocket
sockSrvr、sockRecv;
用于监听和发送文件的套接字
套接字类CClientSocket、CListeningSocket分别用于消息的发送和监听;CMsg用于消息的存储;CPortDlg类用于首次登陆服务器端时IP地址及端口的设置。
登录对话框如图3所示。
图3端口设置
2.客户端
四个窗口类CInputView、CLeftView、CMessageView、CSmallView分别用于消息的输入、在线用户的显示、消息记录的显示和文件接收窗口。
同样通过在主框架中对窗口进行分割成3部分并映射给三个视图类。
分割结果如图所示。
图4客户端窗口
客户端窗口类的成员函数及变量如表2所示。
表格2客户端视图类
类名
成员函数或变量
作用
CInputView
voidCInputView
OnChar(UINTnChar,UINTnRepCnt,UINTnFlags)
输入窗口与聊天窗口交互
BOOLCInputView
PreCreateWindow(CREATESTRUCT&cs)
对应窗口的建立
CLeftView
voidCLeftView
OnInitialUpdate()
初始化视图
voidCLeftView
OnDestroy()
删除用户头像
CImageList
*m_pImageList;
存储用户头像
CSmallView
voidCSmallView
OnBnClickedCheck1()
连接服务器
CSocket
sockClient、sockRecv;
用于连接和接收文件的套接字
CMessageView
voidCMessageView
Message(LPCTSTRlpszMessage)
消息的显示
BOOLCMessageView
PreCreateWindow(CREATESTRUCT&cs)
窗口的建立
CChatSocket类用于与服务器端连接及消极的接受;CLogonDlg用于与服务器端连接IP及端口的设计,其需要与服务器端所设置的一致;CMsg类用于消息的存储与表达;CMediaDialog、Cox1、CWM…用于视频播放的窗口的调用和WindowsMediaPlayer控件的使用。
其中连接操作如图5所示及视频播放对话框显示如图6所示。
图5连接参数
图6视频播放对话框
四编程实现
1.窗口化分
服务器端窗口划分代码的实现:
在主窗口MainFrame.cpp中的BOOLCMainFrame:
:
OnCreateClient(LPCREATESTRUCT/*lpcs*/,CCreateContext*pContext)中应用窗口化分函数CreateStatic()、CreatView()等函数实现窗口的划分。
客户端由OnCreateClient()函数实现,具体代码实现为:
BOOLCMainFrame:
:
OnCreateClient(LPCREATESTRUCT/*lpcs*/,
CCreateContext*pContext)
{
if(!
m_wndSplitter.CreateStatic(this,1,2))
returnFALSE;
if(!
m_wndSplitter1.CreateStatic(
&m_wndSplitter,2,1,
WS_CHILD|WS_VISIBLE|WS_BORDER,
m_wndSplitter.IdFromRowCol(0,0)
))
{
TRACE0("Failedtocreatenestedsplitter\n");
returnFALSE;
}
if(!
m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CLeftView),CSize(100,100),pContext))
{
m_wndSplitter.DestroyWindow();
m_wndSplitter1.DestroyWindow();
returnFALSE;
}
if(!
m_wndSplitter1.CreateView(1,0,RUNTIME_CLASS(CChatView),CSize(100,100),pContext))
{
m_wndSplitter.DestroyWindow();
m_wndSplitter1.DestroyWindow();
returnFALSE;
}
if(!
m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CSmallView),CSize(100,100),pContext))
{
m_wndSplitter.DestroyWindow();
returnFALSE;
}
m_wndSplitter.SetColumnInfo(0,450,100);
m_wndSplitter1.SetRowInfo(0,250,100);
returnTRUE;
returnTRUE;
}
BOOLCMainFrame:
:
OnCreateClient(LPCREATESTRUCT/*lpcs*/,
CCreateContext*pContext)
{
//创建划分窗口
if(!
m_wndSplitter.CreateStatic(this,2,2))
returnFALSE;
CRectrectClient;
GetClientRect(rectClient);
intnWidth=rectClient.right-rectClient.left;
intnHeight=rectClient.bottom-rectClient.top;
if(!
m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMessageView),CSize(nWidth/2.0,nHeight/2.0),pContext))
{
m_wndSplitter.DestroyWindow();
returnFALSE;
}
if(!
m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CInputView),CSize(nWidth/2.0,nHeight/2.0),pContext))
{
m_wndSplitter.DestroyWindow();
returnFALSE;
}
if(!
m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CSmallView),CSize(nWidth/2.0,nHeight/2.0),pContext))
{
m_wndSplitter.DestroyWindow();
returnFALSE;
}
if(!
m_wndSplitter.CreateView(1,1,RUNTIME_CLASS(CLeftView),CSize(nWidth/2.0,nHeight/2.0),pContext))
{
m_wndSplitter.DestroyWindow();
returnFALSE;
}
}
2.消息发送与接收
服务器端消息的发送与接收是由ReadMsg()和SendMsg()两个函数完成的,具体代码实现如下:
CMsg*CChatServerDoc:
:
ReadMsg(CClientSocket*pSocket)
{
staticCMsgmsg;
TRY
{
//接收数据
pSocket->ReceiveMsg(&msg);
//如果是新用户则更新用户列表
if(msg.code==SENDING_NICKNAME)
{
UpdateChattersList(msg.m_strText);
}
if(msg.code==LEAVING_CHAT)
{
DeleteChatter(msg.m_strText,&msg);
}
//如果是普通消息,则更新聊天信息列表。
并将信息加入到m_msgList中。
if(msg.code==NORMAL_MESSAGE)
{
Message(msg.m_strText);
m_msgList.AddTail(msg.m_strText);
}
}
CATCH(CFileException,e)
{
CStringstrTemp;
if(strTemp.LoadString(IDS_READERROR))
Message(strTemp);
msg.m_bClose=TRUE;
pSocket->Abort();
}
END_CATCH
return&msg;
}
voidCChatServerDoc:
:
SendMsg(CClientSocket*pSocket,CMsg*pMsg)
{
TRY
{
//调用CClientSocket中的函数发送消息
pSocket->SendMsg(pMsg);
}
CATCH(CFileException,e)
{
pSocket->Abort();
CStringstrTemp;
if(strTemp.LoadString(IDS_SENDERROR))
Message(strTemp);
}
END_CATCH
}
3.文件发送与接受
服务器端文件的发送由SendFile()函数完成,客户端的文件接收由ReceiveFile()函数实现,具体代码实现如下:
voidCSmallView:
:
SendFile(LPCTSTRstrFilename)
{
CFilemyFile;
//文件访问方式为只读的二进制方式
//CFile的成员函数Open出错返回0
if(!
myFile.Open(strFilename,CFile:
:
modeRead|CFile:
:
typeBinary))
return;
intmyFileLength=myFile.GetLength();//发送正确的文件大小
sockRecv.Send(&myFileLength,4);
byte*data=newbyte[myFileLength];//分配byte堆,大小就是文件大小
myFile.Read(data,myFileLength);//把文件内容读入堆data中
sockRecv.Send(data,myFileLength);//把堆data中的内容发送出去
myFile.Close();
deletedata;//释放堆
}
voidCSmallView:
:
ReceiveFile(void)//接受文件
{
intdataLength=0;
sockClient.Receive(&dataLength,4);//这里的dataLength是发过来的文件大小
if(dataLength==0)
{
AfxMessageBox("接受失败");
return;
}
byte*data=newbyte[dataLength];
sockClient.Receive(data,dataLength);//接收全部数据
//////////////输出文件名////////////////
CFileDialoghFileDlg(FALSE,NULL,NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_READONLY,TEXT("所有文件t(*.*)|*.*||"),NULL);
hFileDlg.m_ofn.nFilterIndex=1;
hFileDlg.m_ofn.lStructSize=sizeof(OPENFILENAME);
hFileDlg.m_ofn.lpstrTitle=TEXT("保存文件到...\0");
if(hFileDlg.DoModal()!
=IDOK)
{
return;
}
CStringstrPathName=hFileDlg.GetPathName();
m_fname=strPathName;
UpdateData(FALSE);
///////////////////////////////
CFiledestFile(strPathName,CFile:
:
modeCreate|CFile:
:
modeWrite|CFile:
:
typeBinary);
destFile.Write(data,dataLength);//写入磁盘文件
destFile.Close();
deletedata;
}
4.聊天记录及在线信息的保存
服务器端聊天记录的保存由OnSaveList()函数完成,客户端端由Serialize()实现,服务器端用户在线情况存储由OnSaveinformation()函数实现,具体代码实现为:
voidCChatServerDoc:
:
OnSaveList()
{
//////////////弹出窗口/////////////////////////////////
CFileDialoghFileDlg(FALSE,NULL,NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_READONLY,TEXT("所有文件t(*.*)|*.*||"),NULL);
hFileDlg.m_ofn.nFilterIndex=1;
hFileDlg.m_ofn.lStructSize=sizeof(OPENFILENAME);
hFileDlg.m_ofn.lpstrTitle=TEXT("保存用户信息...\0");
if(hFileDlg.DoModal()!
=IDOK)
{
return;
}
CStringstrPathName=hFileDlg.GetPathName();
CFilefile(strPathName,CFile:
:
modeCreate|CFile:
:
modeWrite);
CArchivear(&file,CArchive:
:
store|CArchive:
:
bNoFlushOnDelete);
///////////////////////////////////////////////
////////////保存用户信息///////////////////////////////////
POSITIONrPOS=m_msgList.GetHeadPosition();
while(rPOS!
=NULL)
{
ar< } ar.Close(); file.Close(); } voidCChatClientDoc: : Serialize(CArchive&ar) { if(ar.IsStoring()) { for(POSITIONpos=GetFirstViewPosition();pos! =NULL;) { CView*pView=GetNextView(pos); CMessageView*pChatView=DYNAMIC_DOWNCAST(CMessageView,pView); if(pChatView! =NULL) pChatView->Serialize(ar); } } } voidCLeftView: : OnSaveinformation()//用户在线信息保存 { CFileDialogdlg(FALSE,NULL,NULL,OFN_EXPLORER|OFN_PATHMUSTEXIST,_T("TextFIles(*.txt)|*.txt")); if(IDOK! =dlg.DoModal()) { return; } CStringstrPathName=dlg.GetPathName(); intnCount=GetTreeCtrl().GetCount(); CStringstrinfo=_T("用户名\t\t登陆时间\r\n"); CFilemyFile(strPathName,CFile: : modeCreate|CFile: : modeReadWrite); CArchivear(&myFile,CArchive: : store); ar< HTREEITEMhItem=GetTreeCtrl().GetRootItem(); while(hItem! =NULL) { ar< hItem=GetTreeCtrl().GetNextItem(hItem,TVGN_NEXT); } ar.Close(); myFile.Close(); } 5.视频音乐播放 采用非模态方式打来播放器对话框,可以一边聊天一边听歌看视频,视频音乐的播放有按钮相应函数OnBnClickedOpen(),OnBnClickedOpen1()实现,具体代码为: voidCMediaDialog: : OnBnClickedOpen()//视频播放 { CFileDialoghFileDlg(FALSE,NULL,NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_READONLY,TEXT("所有文件t(*.*)|*.*||"),NULL); hFileDlg.m_ofn.nFilterIndex=1; =sizeof(OPENFILENAME); hFileDlg.m_ofn.lpstrTitle=TEXT("打开文件到...\0"); if(hFileDlg.DoModal()==IDOK) { CStringstrPathName=hFileDlg.GetPathName(); strPathName.MakeUpper(); m_player.openPlayer(strPathName); } } voidCMediaDialog: : OnBnClickedOpen2()//音乐播放 { CFileDialoghFileDlg(FALSE,NULL,NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_READONLY,TEXT("所有文件t(*.*)|*.*||"),NULL); hFileDlg.m_ofn.nFilterIndex=1; hFileDlg.m_ofn.lStructSize=sizeof(OPENFILENAME); hFileDlg.m_ofn.lpstrTitle=TEXT("打开文件到...\0"); if(hFileDlg.DoModal()==IDOK) { CStringstrPathName=hFileDlg.GetPathName();
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 面向 对象 作业