聊天室程序系统方案_第1页
聊天室程序系统方案_第2页
聊天室程序系统方案_第3页
聊天室程序系统方案_第4页
聊天室程序系统方案_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

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

文档简介

..长沙广播电视大学毕业设计聊天室软件实现指导学生:__摘要本课程设计实现类似于Windows操作系统自带的聊天程序。在课程设计中,系统开发平台为WindowsXP,程序设计语言采用VisualC++,程序运行平台为Windows98/2000/XP。在程序设计中,主要分别实现服务器端和客户端两部分程序。系统采用C/S结构,可以多人同时在线。程序通过调试运行,实现了设计目标,能够同时满足扫雷游戏初学者和高手的需要。关键词:聊天程序系统;数据库;VisualC++6.0;SQLServer2000AbstractThecourseisdesignedtoachievesimilartoWindowsoperatingsystembringingchatprogram.Inthecurriculumdesign,systemdevelopingplatformforWindowsXP,programminglanguageusingVisualc++,programoperationplatformforWindows98/2000/XP.Inprogramming,mainlyrealizedrespectivelytheserverandclienttwopartprogram.SystemusingC/Sstructure,canpeopleonlineatthesametime.Programthroughthepost-saleservice,realizedthedesigngoal,satisfiesminesweeperbeginnersandsuperiorneeds.Keywords:chatprogramsystem;Database;Visualc++6.0,SQLServer20001绪 论正如大多数聊天室一样,需要在一台计算机上运行服务器端程序,然后就可以在同一网络的其他计算机上运行客户端程序,登录到服务器上。一个聊天服务器和很多客户端进行通信,从而实现把来自不同的客户的聊天信息转交到所有其他的客户端。这样就形成一个采用C/S结构的可以多人同时在线的聊天室。同时本聊天室在设计时完成在线用户显示、私聊功能。私聊功能即是聊天信息只在私聊两方的计算机客户端上显示,其他客户端不显示。2系统分析《聊天程序系统》提供了多个客户端的连接,可以允许多个用户同时在线。本设计主要对聊天室服务器和聊天室客户端两个方面进行实现,其功能:新用户登陆、更新在线用户列表、用户离开、私聊等。3.1功能简介根据用户的需求,要求系统需具有以下功能:<1>聊天室服务器端实现功能:=1\*GB3①支持多个客户端的连接,一个聊天服务器和很多客户端进行通信。=2\*GB3②〔2接收客户端发送的信息,能分析信息的含义。A.如果是新用户登录,则在服务器在线用户列表框中加入新用户昵称,并显示新用户进入信息提示,同时将更新在线用户列表发给所有客户端;B.如果是用户离开,则在服务器在线用户列表框中删除此用户昵称,并显示用户离开信息提示,同时将更新在线用户列表发给所有客户端;C.如果是私聊,聊天信息则显示在服务器聊天信息列表框中,同时将聊天信息仅仅发给私聊对象客户端;D.如果是公开聊天信息则显示在服务器聊天信息列表框中,同时将聊天信息发给所有客户端。〔3服务器停止服务时,停止端口侦听,将停止服务信息发给所有客户端。二、聊天室客户端实现功能:〔1支持连接指定IP的聊天服务器。〔2私聊形式或公开形式发送聊天信息给聊天服务器。〔3接收服务器端发送的信息,能分析信息的含义。A.如果是用户离开,则在在线用户列表框中删除此用户昵称;B.如果是更新在线用户列表,则客户端重新显示在线用户。3.2系统特点A.界面设计美观友好B.规范、完善的基础信息设置C.信息查询灵活、方便、快捷D.系统运行稳定,安全可靠3.34总体设计4.1细化聊天室程序通信规程我们通过Socket发送一定格式的字符串来完成不同的操作。具体格式为:命令|参数|参数……〔1新用户登录NEW_USER|昵称〔2更新在线用户列表USERLIST|昵称|昵称|昵称……〔3用户离开CLOSEUSE|昵称〔4私聊PrivChat|私聊对象|私聊内容〔含两方的昵称注意:公开的聊天信息,则没有设置相应命令。在判断不是上述情况后,则就是公开的聊天信息。4.2客户端工作流程〔1用户输入服务器端的IP和昵称后,单击连接聊天服务器按钮,客户端程序将建立一个连接套接字Socket与服务器端连接,如果成功,将昵称通过这个Socket发送到服务器端。〔2用户输入聊天信息后,单击发送信息按钮,通过这个Socket来发送给服务器。〔3用户如果单击"私聊"复选框,单击发送信息按钮后,先判断是否选择私聊对象,在发出"PrivChat|私聊对象|私聊内容"。〔4当客户端单击"离开聊天室"按钮断开连接前向服务器发出"CLOSEUSE|昵称"信息。4.3服务器段工作流程〔1单击启动按钮,服务器端通过create<>调用创建一个侦听套接字Socket后与指定的本地端口6767绑定,就可以在该端口进行侦听listen<>。〔2如果有客户端连接请求,将触发侦听套接字的OnAccept事件,在事件处理函数中,创建新的连接套接字,用于与客户端的通信。并将该连接套接字Socket加入链表类CClientSocketList指针List〔&CCSL所指的链表中。〔3每当一个连接套接字Socket接收到信息,都将会触发服务器端对应的连接套接字的OnReceive事件。在OnReceive事件处理函数中,读取客户端发送的聊天信息,根据细化聊天室程序通信规程进行分析。如果是新用户登录或用户离开或公开聊天信息,则再把接收到的信息发送给每一个连接套接字Socket。如果是新用户登录或用户离开或私聊信息,则发给找到的私聊对象。〔4当客户端断开连接前向服务器发出"CLOSEUSE|昵称"。服务器在OnReceive事件处理函数中在List所指的链表中释放该连接套接字,并同时将更新在线用户列表发给所有客户端。〔5当单击聊天室服务器"停止"按钮,停止端口侦听,广播聊天服务器停止消息,释放链表CCSL中套接字,清除服务器在线用户列表。4.3设计目标本系统是根据用户的实际需求而开发的,完全能够实现对用户的自动化管理,通过本系统可以达到以下目标:A.系统运行稳定,安全可靠。B.界面设计美观,人机交互界面友好。C.信息查询灵活、方便、快捷、准确,数据存储安全可靠。D.满足键盘和鼠标的双重操作,完全支持回车键。E.采用多种方式查询数据。F.操作员可以随时修改自己的口令。G.对用户输入的数据,系统进行严格的数据检验,尽可能排除人为的错误。H,数据保密性强,为每个用户设置相应的权限级别。5系统设计5.1开发及运行环境软件要求操作系统:Windows2000/NT/XP/CE。数据库:SQLServer2000。聊天室客户端设计我们要做的客户端分需要输入一些登录信息,如下图1-1所示。其中上方有两个编辑框,其中一个输入用户昵称信息,另一个用于输入服务器IP地址信息。聊天室客户端窗口中间有两个列表框,一个显示用户聊天信息,另一个显示在线用户昵称信息。下方发言边的编辑框,用于输入聊天信息。两个按钮,一个用来发送信息,另一个用来关闭聊天室客户端窗口,退出聊天室。图1-1聊天室客户端窗口其实现过程:<1>启动VC,利用MFCAppWizard[EXE]建立一个新的MFC程序,取名为ChatRoom,在MFCAppWizardStep1的时候我们选择Dialogbased,在Step2时我们一定要选择上WindowsSockets选项,之后的几步我们就可以使用默认值了。聊天室客户端窗口是AppWizard生成的时候建立的。图1-2MFCAppWizardStep22.创建连接套接字CClientSocket类按CTRL+W利用类向导添加一个基类为CSocket类的CClientSocket类,其中有一个很重要的是重载虚成员函数OnReceive〔,它调用了主对话框的成员函数GetMessage来实现了立即显示从服务器获得的聊天信息到聊天室客户端窗口对话框中的功能。在CClientSocket类中添加一个指向对话框类的数据成员myDlg,NikeName。一个成员函数SetDlg。黑体为新增或修改过的代码。//ClientSocket.h:headerfileclassCChatRoomDlg;//CClientSocketcommandtargetclassCClientSocket:publicCSocket{//Attributespublic: CChatRoomDlg*myDlg;//添加数据成员 CStringNikeName;//添加数据成员 BOOLSetDlg<CChatRoomDlg*tmp>;//添加一个成员函数//Overridespublic: //ClassWizardgeneratedvirtualfunctionoverrides //{{AFX_VIRTUAL<CClientSocket> public: virtualvoidOnReceive<intnErrorCode>;//重载的虚成员函数OnReceive //}}AFX_VIRTUAL……..protected:};//ClientSocket.cpp:implementationfile#include"stdafx.h"#include"ChatRoom.h"#include"ClientSocket.h"#include"ChatRoomDlg.h"#include"ChatRoomDlg.h"CClientSocket::CClientSocket<>{ NikeName=""; myDlg=0;}BOOLCClientSocket::SetDlg<CChatRoomDlg*tmp>{ myDlg=tmp; returntrue;}voidCClientSocket::OnReceive<intnErrorCode>{myDlg->GetMessage<>;//调用了主对话框的成员函数GetMessage来显示聊天信息CSocket::OnReceive<nErrorCode>;}3.聊天室客户端窗口应用程序定义连接套接字CClientSocket类全局变量,传递到对话框中。//ChatRoom.cpp#include"ClientSocket.h"CClientSocketcurSocket;//全局变量curSocketBOOLCChatRoomApp::InitInstance<>{if<!AfxSocketInit<>>{AfxMessageBox<IDP_SOCKETS_INIT_FAILED>;returnFALSE;}AfxEnableControlContainer<>;//Standardinitialization#ifdef_AFXDLLEnable3dControls<>;//CallthiswhenusingMFCinasharedDLL#elseEnable3dControlsStatic<>;//CallthiswhenlinkingtoMFCstatically#endif CChatRoomDlgdlg<&curSocket>; m_pMainWnd=&dlg; curSocket.SetDlg<&dlg>; intnResponse=dlg.DoModal<>; if<nResponse==IDOK> { //TODO:Placecodeheretohandlewhenthedialogis //dismissedwithOK } elseif<nResponse==IDCANCEL> { //TODO:Placecodeheretohandlewhenthedialogis //dismissedwithCancel }returnFALSE;}4.需要在默认建立的主对话框上删除已有控件。聊天室客户端窗口对话框中的控件可以按表5-2建立。表5-2聊天室客户端控件属性表控件属性属性值控件成员变量变量类型标签Caption昵称编辑框m_IDC_EDIT_MESSAGECString标签Caption聊天室IP编辑框m_IDC_EDIT_ADDRESSCString按钮Caption连接聊天服务器IDConnect_Button编辑框m_IDC_EDIT_MESSAGECString列表框IDIDC_LIST1m_ChatListCListBOXGroupBoxCaption在线用户列表列表框IDIDC_USERm_USERCListBOX复选框IDIDC_CHECK1m_SLBOOL按钮Caption发送信息m_BNSendCButtonIDSend_Button按钮Caption离开聊天室m_BNExitCButtonIDExit_Button其中m_IDC_EDIT_MESSAGE是发送信息框。修改对话框ChatRoomDlg的构造函数以及添加一个指向连接套接字的myServerSocket成员变量。//ChatRoomDlg.h:headerfile#include"ClientSocket.h"classCChatRoomDlg:publicCDialog{//Constructionpublic: BOOLGetMessage<>; CChatRoomDlg<CClientSocket*tmp,CWnd*pParent=NULL>; CClientSocket*myServerSocket;//DialogData //{{AFX_DATA<CChatRoomDlg> enum{IDD=IDD_CHATROOM_DIALOG}; CButton m_BNExit; CButton m_BNSend; CListBox m_IDC_LIST_CHATBOX_CONTROL; CListBox m_USER; CString m_IDC_EDIT_MESSAGE; CString m_IDC_EDIT_ADDRESS; CString m_IDC_EDIT_NIKENAME; BOOL m_SL; //}}AFX_DATA……};5.对话框类中的函数聊天客户端CChatRoomDlg对话框初始化OnInitDialog<>函数中添加代码实现"发送信息"按钮状态为无效;"离开聊天室"按钮状态为无效。添加客户端窗口的"连接服务器"按钮响应响应函数OnConnectButton<>。它处理网络连接,如果连接服务器成功,发送成功登陆者昵称给服务器端接收,服务器端判断NEW_USER,知道新用户登陆,将更新在线用户列表字符串后,转发给各个客户端中显示。添加客户端窗口的"发送信息"按钮单击响应函数OnButton1<>。它首先判断私聊复选框是否选中,如果选中则要保证选择私聊对象,将发出的信息以"PrivChat|+私聊对象+|登陆昵称+悄悄对+私聊对象+说+发送信息框的内容"的形式发给服务器端。服务器端判断首为PrivChat从而知道按私聊信息处理。如果未选中,则不含自定义格式。仅仅以"登陆昵称+说+发送信息框的内容"的形式发给服务器端。添加聊天室客户端窗口"退出聊天室"按钮的单击响应函数OnButton2<>。它首先发送断开信息"CLOSEUSE|登陆昵称"后,关闭对话框。添加聊天室客户端窗口对话框的成员函数GetMessage〔。它通过调用连接套接字的Receive〔接收服务器端信息,根据细化聊天室程序通信规程来显示聊天信息或更新在线用户列表。//ChatRoomDlg.cpp:implementationfile#include"stdafx.h"#include"ChatRoom.h"#include"ChatRoomDlg.h"#ifdef_DEBUG#definenewDEBUG_NEW#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endifCClientSocketcurSocket;CChatRoomDlg::CChatRoomDlg<CClientSocket*tmp,CWnd*pParent> :CDialog<CChatRoomDlg::IDD,pParent>{ //{{AFX_DATA_INIT<CChatRoomDlg> m_IDC_EDIT_MESSAGE=_T<"">; m_IDC_EDIT_ADDRESS=_T<"">; m_IDC_EDIT_NIKENAME=_T<"">; m_SL=FALSE; //}}AFX_DATA_INIT //NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32 m_hIcon=AfxGetApp<>->LoadIcon<IDR_MAINFRAME>;myServerSocket=tmp;}BOOLCChatRoomDlg::OnInitDialog<>{//………..SetIcon<m_hIcon,TRUE>; //Setbigicon SetIcon<m_hIcon,FALSE>; //Setsmallicon //TODO:Addextrainitializationhere m_BNSend.EnableWindow<FALSE>;//"发送信息"按钮状态为无效 m_BNExit.EnableWindow<FALSE>;//"离开聊天室"按钮状态为无效 returnTRUE;//returnTRUEunlessyousetthefocustoacontrol}voidCChatRoomDlg::OnConnectButton<>//"连接服务器"按钮响应函数{ //TODO:AddyourcontrolnotificationhandlercodehereUpdateData<TRUE>;char*nikename,*address;intn;if<!myServerSocket->Create<>>{myServerSocket->Close<>;AfxMessageBox<"网络创建错误!!">;return;}n=m_IDC_EDIT_ADDRESS.GetLength<>;address=newchar<n+1>;sprintf<address,"%s",m_IDC_EDIT_ADDRESS.GetBuffer<n>>;address[n]=0;n=m_IDC_EDIT_NIKENAME.GetLength<>;nikename=newchar<n+1>;sprintf<nikename,"%s",m_IDC_EDIT_NIKENAME.GetBuffer<n>>;nikename[n]=0;if<!myServerSocket->Connect<address,6767>>{myServerSocket->Close<>;AfxMessageBox<"网络连接错误,请检查服务器地址。">;return;}m_BNSend.EnableWindow<TRUE>;//"发送信息"按钮状态为有效m_BNExit.EnableWindow<TRUE>;//"离开聊天室"按钮状态为有效myServerSocket->NikeName=nikename;//*********************发送新用户昵称charmessage2[20];strcpy<message2,"NEW_USER|">;strcat<message2,myServerSocket->NikeName>; if<myServerSocket->Send<message2,20>> { }else { AfxMessageBox<"网络传输错误!!!">; }}voidCChatRoomDlg::OnButton1<>//发送按钮的函数{ //TODO:Addyourcontrolnotificationhandlercodehereintn;charmessage[1000];CStringto_name;UpdateData<TRUE>;if<m_SL==TRUE>//私聊{ if<m_USER.GetCurSel<>>=0> { m_USER.GetText<m_USER.GetCurSel<>,to_name>; m_IDC_EDIT_MESSAGE=myServerSocket->NikeName+"悄悄对"+to_name+"说"+m_IDC_EDIT_MESSAGE; m_IDC_LIST_CHATBOX_CONTROL.AddString<m_IDC_EDIT_MESSAGE>;m_IDC_EDIT_MESSAGE="PrivChat|"+to_name+"|"+m_IDC_EDIT_MESSAGE; n=m_IDC_EDIT_MESSAGE.GetLength<>;sprintf<message,"%s",m_IDC_EDIT_MESSAGE.GetBuffer<n>>; message[n]=0; } else { AfxMessageBox<"没有选择私聊对象!">; return; }}else{m_IDC_EDIT_MESSAGE=myServerSocket->NikeName+"对大家说:"+m_IDC_EDIT_MESSAGE;n=m_IDC_EDIT_MESSAGE.GetLength<>; sprintf<message,"%s",m_IDC_EDIT_MESSAGE.GetBuffer<n>>;message[n]=0;}if<myServerSocket->Send<message,n+1>>{m_IDC_EDIT_MESSAGE="";UpdateData<FALSE>;}else{AfxMessageBox<"网络传输错误!">;}}voidCChatRoomDlg::OnButton2<>//离开按钮的函数{ //TODO:Addyourcontrolnotificationhandlercodehere //发送断开信息 charmessage2[20]; strcpy<message2,"CLOSEUSE|">; strcat<message2,myServerSocket->NikeName>; if<myServerSocket->Send<message2,20>> { } else { AfxMessageBox<"网络传输错误!!!">; } myServerSocket->Close<>; CDialog::OnOK<>;}BOOLCChatRoomDlg::GetMessage<>//显示聊天信息{ charbuff[2000]; charname[20]; intcount; count=myServerSocket->Receive<buff,2000>; buff[count]=0; charFlag[10]; for<inti=0;i<8;i++>Flag[i]=buff[i]; Flag[8]=0; if<strcmp<Flag,"USERLIST">==0>//新用户昵称列表{ m_USER.ResetContent<>;CStringsTemp; intj=8; for<i=8;buff[i]!=0;i++> { if<buff[i]=='|'>//昵称分割符号 {for<intm=0;j<i;j++,m++> name[m]=buff[j]; name[m]='\0'; sTemp.Format<"%s",name>;//昵称m_USER.AddString<sTemp>; j=i+1; } } } else//聊天信息 { m_IDC_LIST_CHATBOX_CONTROL.AddString<buff>; } returntrue;}这就是聊天室客户端程序。聊天室服务器端设计我们要做的服务端界面设计如下图1-3所示。聊天室服务器窗口有两个列表框,一个显示用户聊天信息,另一个显示在线用户昵称信息。其中"启动"按钮、"停止"按钮分别是启动和中止聊天服务的。其实现过程:1.首先利用MFCAppWizard[EXE]建立一个新的MFC程序,取名为ChatRoomServer,在MFCAppWizardStep1的时候我们选择Dialogbased,注意一定不要忘记在Step2时钩上WindowsSockets。2.需要在默认建立的主对话框上删除已有控件,增加表2-2所列控件:表2-2聊天室服务端控件属性表控件属性属性值控件成员变量变量类型列表框IDIDC_USERm_USERCListBOX列表框IDIDC_LIST1m_ChatListCListBOXGroupBoxCaption在线用户列表按钮1Caption启动m_IDC_BUTTON_STARTCButtonIDIDC_Button1按钮2Caption停止m_IDC_BUTTON_STOPCButtonIDIDC_Button2用ClassWizard为这两个按钮增加上对应的函数:OnButtonStart<>、OnButtonStop<>。按钮对应的函数中ListenSocket成员变量是CListenSocket类类型。在ChatRoomServerDlg.cpp中的对话框初始化OnInitDialog函数中,控制"停止"按钮状态为无效。在ChatRoomServerDlg.Cpp文件中添加头文件:#include"ListenSocket.h"。/ChatRoomServerDlg.Cpp其具体内容如下:#include"stdafx.h"#include"ChatRoomServer.h"#include"ChatRoomServerDlg.h"#include"ListenSocket.h"BOOLCChatRoomServerDlg::OnInitDialog<>{ CDialog::OnInitDialog<>;…… SetIcon<m_hIcon,TRUE>; //Setbigicon SetIcon<m_hIcon,FALSE>; //Setsmallicon //TODO:Addextrainitializationhere m_IDC_BUTTON_STOP.EnableWindow<FALSE>;//"停止"按钮状态为无效 returnTRUE;}voidCChatRoomServerDlg::OnButtonStart<>{//TODO:Addyourcontrolnotificationhandlercodeherem_IDC_BUTTON_START.EnableWindow<FALSE>;ListenSocket.Create<6767>;//绑定端口6767ListenSocket.Listen<>;//服务器侦听m_IDC_BUTTON_STOP.EnableWindow<TRUE>;}voidCChatRoomServerDlg::OnButtonStop<>{ //TODO:Addyourcontrolnotificationhandlercodehere m_IDC_BUTTON_STOP.EnableWindow<FALSE>; chars[30]="聊天服务器停止工作了!!!";ListenSocket.CCSL.Sends<s,30>;//广播聊天服务器停止消息CClientSocket*p=ListenSocket.CCSL.Head; while<p> { p->Close<>; ListenSocket.CCSL.Del<p>;//释放链表中套接字 p=ListenSocket.CCSL.Head; }ListenSocket.Close<>;m_USER.ResetContent<>;//清除服务器在线用户列表m_IDC_BUTTON_START.EnableWindow<TRUE>;}3.创建侦听套接字CListenSocket类利用类向导创建一个基类为Csocket的CListenSocket类,在CListenSocket类中增加CClientSocketListCCSL变量;增加一个虚函数OnAccept。//ListenSocket.h头文件#include"ClientSocketList.h"//addclassCListenSocket:publicCSocket{//Attributespublic://Operationspublic:CClientSocketListCCSL;CListenSocket<>;virtual~CListenSocket<>;//Overridespublic://ClassWizardgeneratedvirtualfunctionoverrides//{{AFX_VIRTUAL<CListenSocket>public:virtualvoidOnAccept<intnErrorCode>;//}}AFX_VIRTUAL//Generatedmessagemapfunctions//{{AFX_MSG<CListenSocket>//NOTE-theClassWizardwilladdandremovememberfunctionshere.//}}AFX_MSG//Implementationprotected:};//CListenSocket.cpp具体内容如下#include"stdafx.h"#include"ChatRoomServer.h"#include"ListenSocket.h"#include"ClientSocketList.h"//add#include"ClientSocket.h"//addCListenSocket::CListenSocket<>{}CListenSocket::~CListenSocket<>{}//Donoteditthefollowinglines,whichareneededbyClassWizard.#if0BEGIN_MESSAGE_MAP<CListenSocket,CSocket> //{{AFX_MSG_MAP<CListenSocket> //}}AFX_MSG_MAPEND_MESSAGE_MAP<>#endif //0voidCListenSocket::OnAccept<intnErrorCode>{//TODO:Addyourspecializedcodehereand/orcallthebaseclassCClientSocket*tmp=newCClientSocket<&CCSL>;//创建新的连接套接字Accept<*tmp>;CCSL.Add<tmp>;//新的连接套接字加入套接字链表CSocket::OnAccept<nErrorCode>;}4.创建套接字链表类CClientSocketList利用类向导创建一个为生成客户Sockets队列的链表类CClientSocketList类,"ClassType"列表框选择GenericClass,如下图2-4所示。图2.4基类GenericClass的派生类其中的成员变量Head指针是由CSocket直接派生出来的CClientSocket类。CClientSocketList类构造函数完成head初始化,同时增加将Socket加入链表队列Add〔函数、仅仅向私聊用户发送信息OnlySend〔函数、链表队列中删除Socket的Del〔函数、所有用户发送聊天信息Sends〔函数。//CClientSocketList.h#include"ClientSocket.h"classCClientSocketList{public: BOOLDel<CClientSocket*>;BOOLOnlySend<char*buff,intn,intwho>; BOOLSends<char*buff,intn>;BOOLAdd<CClientSocket*>;CClientSocket*Head; CClientSocketList<>; virtual~CClientSocketList<>;};//ClientSocketList.cpp#include"stdafx.h"#include"ChatRoomServer.h"#include"ClientSocketList.h"#include"ClientSocket.h"//addCClientSocketList::CClientSocketList<>{ Head=0;}BOOLCClientSocketList::Add<CClientSocket*add>//将Socket加入链表队列{CClientSocket*tmp=Head;if<!Head>{ Head=add;returnfalse;}while<tmp->Next>tmp=tmp->Next;tmp->Next=add;returntrue;}BOOLCClientSocketList::Del<CClientSocket*d>//链表队列中删除Socket{CClientSocket*p1=Head;CClientSocket*p2;if<!Head>{returnfalse;}if<Head==d>{Head=p1->Next; p1->Close<>; deletep1;returntrue;}for<;p1->Next!=NULL;p1=p1->Next>{ if<p1->Next==d> { p2=p1->Next; p1->Next=p2->Next; p2->Close<>; deletep2;returntrue; }}returnfalse;}BOOLCClientSocketList::Sends<char*buff,intn>//所有用户发送信息{CClientSocket*curr=Head;while<curr>{curr->Send<buff,n>;curr=curr->Next;}returntrue;}BOOLCClientSocketList::OnlySend<char*buff,intn,intwho>//仅仅向私聊用户who发送信息{CClientSocket*curr=Head;while<curr&&who>0>{ curr=curr->Next; who--;}curr->Send<buff,n>;returntrue;}5.创建连接套接字CClientSocket类利用类向导创建一个基类为Csocket类的CClientSocket类,CClientSocket类中增加CClientSocket<CClientSocketList*>构造函数;增加一个虚函数OnReceive〔。它接收客户端的信息,根据细化聊天室程序通信规程来转发聊天信息或更新在线用户列表。三个指针变量List、Front、Next。//ClientSocket.h如下classCClientSocketList;classCChatRoomServerDlg;classCClientSocket:publicCSocket{//Attributespublic:CChatRoomServerDlg*myDlg;//Operationspublic: CClientSocket<>; CClientSocket<CClientSocketList*>; virtual~CClientSocket<>;//Overridespublic: BOOLSetDlg<CChatRoomServerDlg*tmp>;classCClientSocket:publicCSocket{//Attributespublic://Operationspublic:CClientSocket<CClientSocketList*>;virtual~CClientSocket<>;//Overridespublic:CClientSocketList*List;CClientSocket*Front;CClientSocket*Next;//ClassWizardgeneratedvirtualfunctionoverrides//{{AFX_VIRTUAL<CClientSocket>public:virtualvoidOnReceive<intnErrorCode>;virtualvoidOnClose<intnErrorCode>;//}}AFX_VIRTUAL//Generatedmessagemapfunctions//{{AFX_MSG<CClientSocket>//NOTE-theClassWizardwilladdandremovememberfunctionshere.//}}AFX_MSG//Implementationprotected:};//ClientSocket.cpp#include"stdafx.h"#include"ChatRoomServer.h"#include"ClientSocket.h"#include"ClientSocketList.h"//add#include"ChatRoomServerDlg.h"//addCClientSocket::CClientSocket<>{myDlg=0;}CClientSocket::CClientSocket<CClientSocketList*tmp>{ Front=0; Next=0; List=tmp;}BOOLCClientSocket::SetDlg<CChatRoomServerDlg*tmp>{ myDlg=tmp;//用来获取对话框指针 returntrue;} voidCClientSocket::OnReceive<intnErrorCode>{ charbuff[1000]; charall_user[2000]; charname[20];intn,m;n=this->Receive<buff,1000>;buff[n]=0; charFlag[10]; for<inti=0;i<8;i++>Flag[i]=buff[i]; Flag[8]=0; //下面两行代码用来获取对话框指针CChatRoomServerApp*pApp=<CChatRoomServerApp*>AfxGetApp<>;CChatRoomServerDlg*pDlg=<CChatRoomServerDlg*>pApp->m_pMainWnd; if<strcmp<Flag,"NEW_USER">==0>//新用户加入{ CStringsTemp; for<i=9;buff[i]!=0;i++> buff[i-9]=buff[i];buff[i-9]=0; sTemp.Format<"%s",buff>;//新用户昵称sTemp pDlg->m_USER.AddString<sTemp>;//新的在线用户昵称名单发给所有用户 m=pDlg->m_USER.GetCount<>; strcpy<all_user,"USERLIST">; for<i=0;i<m;i++> { pDlg->m_USER.GetText<i,name>; strcat<all_user,name>; strcat<all_user,"|">; }strcat<buff,"进入聊天室">; List->Sends<all_user,strlen<all_user>>; } elseif<strcmp<Flag,"CLOSEUSE">==0>//用户退出 { CStringsTemp; for<i=9;buff[i]!=0;i++> buff[i-9]=buff[i];buff[i-9]=0; sTemp.Format<"%s",buff>;//离线用户昵称 m=pDlg->m_USER.GetCount<>;for<i=0;i<m;i++>//查找离线用户在列表框的索引号 { pDlg->m_USER.GetText<i,name>; if<strcmp<name,buff>==0> pDlg->m_USER.DeleteString<i>; } //新的在线用户昵称名单发给所有用户 m=pDlg->m_USER.GetCount<>; strcpy<all_user,"USERLIST">; for<i=0;i<m;i++> { pDlg->m_USER.GetText<i,name>; strcat<all_user,name>; strcat<all_user,"|">; } strcat<buff,"离开聊天室">; List->Sends<all_user,strlen<all_user>>; List->Del<this>; } else//**** if<strcmp<Flag,"PrivChat">==0>//私聊 { CStringsTemp; for<i=9;buff[i]!='|';i++> buff[i-9]=buff[i];buff[i-9]=0; sTemp.Format<"%s",buff>;//私聊对象昵称for<intk=i+1;buff[k]!=0;k++> buff[k-i-1]=buff[k];buff[k-i-1]=0; m=pDlg->m_USER.GetCount<>;for<i=0;i<m;i++>//查找离线用户在列表框的索引号 { pDlg->m_USER.GetText<i,name>; if<strcmp<name,sTemp>==0> { List->OnlySend<buff,strlen<buff>,i>; } } } else //聊天信息群发给所有用户 { List->Sends<buff,n>; } //Receive只能接受一次,除非下次发送触发后 CStringsTemp; sTemp.Format<"收到:%s",buff>; pDlg->m_ChatList.AddString<sTemp>; pDlg->m_ChatList.SetTopIndex<pDlg->m_ChatList.GetCount<>-1>; CSocket::OnReceive<nErrorCode>;}这样聊天室服务器端就做好了。结束语本次课程设计让我初步了解了聊天系统所涉及到的有关技术、方法,做到了能图、文、并茂地演示了聊天室程序系统。在这次课程设计过程中,遇到了很多问题,我利用图书馆和搜索引擎,查阅资料,同时指导老师也给了我很多帮助,最终问题都得到了解决。通过这次课程设计,我也学到了很多新知识,并且对以前的知识进行了回顾。通过不断上机实验,调试程序,总结经验,增强了动手实践能力和解决问题的能力。虽然这样,因为各种各样的原因,本系统存在的问题还有很多,结构图也不是很详细,客户端和服务端的界面也不是很直观,可能是这方面的知识还是很匮乏。但是,能做到这样,作为一个菜鸟的我还是很欣慰的啦!心得体会:这次做课程设计,我发现我自己存在的问题还是有很多,虽然很多问题我都通过查阅资料和询问老师、同学得到了解决,但这确实是知识的匮乏。所以,我觉得在今后的学习生涯中,一定要注重理论知识的学习和实践能力的锻炼。虽说现在我们的VC++课程结束了,但我觉得有必要去回顾,说不定今天的某天我们还是会用到,说到这,我就得好好感谢我们的任课老师了,让我了解了VC++,虽然不是真的了解,有些东西可能还是一知半解,但多多少少还是懂了点。同时,通过这次设计,我还发现了一点,理论还是要和实践相结合。自己知道的和能做的结合起来这才是最大的成果,我今后一定要向着这个方向努力,力争做到最好。参考文献[1]DavidFreeman.CreatingEmotioninGames[M].北京:红旗出版社,2003.3~30[2]陈卡. DirectX93D图形程序设计[M]. 上海:上海科技出版社,2003[3]中国网游研发中心网[EB/OL]. ,2006[4]郑阿奇,丁有和.《VisualC++教程》.机械工业出版社.20XX12月.[5]张卫华,刘征,赵志刚,《VisualC++程序设计实战训练》.人民邮电出版社.[6]宋昆,李严《SQLServer数据库开发实例解析》.机械工业出版社.附录<源代码>//tcpseverDlg.cpp:implementationfile#include"stdafx.h"#include"tcpsever.h"#include"tcpseverDlg.h"#ifdef_DEBUG#definenewDEBUG_NEW#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endifcsocketcslisten,csrev[20];intcsnum=0;charname[20][100];CStringsevername;//CAboutDlgdialogusedforAppAboutclassCAboutDlg:publicCDialog{public: CAboutDlg<>; //DialogData //{{AFX_DATA<CAboutDlg> enum{IDD=IDD_ABOUTBOX}; //}}AFX_DATA //ClassWizardgeneratedvirtualfunctionoverrides //{{AFX_VIRTUAL<CAboutDlg>protected: virtualvoidDoDataExchange<CDataExchange*pDX>;//DDX/DDVsupport //}}AFX_VIRTUAL //Implementationprotected: //{{AFX_MSG<CAboutDlg> //}}AFX_MSG DECLARE_MESSAGE_MAP<>};CAboutDlg::CAboutDlg<>:CDialog<CAboutDlg::IDD>{ //{{AFX_DATA_INIT<CAboutDlg> //}}AFX_DATA_INIT}voidCAboutDlg::DoDataExchange<CDataExchange*pDX>{ CDialog::DoDataExchange<pDX>; //{{AFX_DATA_MAP<CAboutDlg> //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP<CAboutDlg,CDialog>//{{AFX_MSG_MAP<CAboutDlg>//Nomessagehandlers//}}AFX_MSG_MAPEND_MESSAGE_MAP<>//CTcpseverDlgdialogCTcpseverDlg::CTcpseverDlg<CWnd*pParent/*=NULL*/>:CDialog<CTcpseverDlg::IDD,pParent>{ //{{AFX_DATA_INIT<CTcpseverDlg> //}}AFX_DATA_INIT //NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32 m_hIcon=AfxGetApp<>->LoadIcon<IDR_MAINFRAME>;}voidCTcpseverDlg::DoDataExchange<CDataExchange*pDX>{ CDialog::DoDataExchange<pDX>; //{{AFX_DATA_MAP<CTcpseverDlg> //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP<CTcpseverDlg,CDialog>//{{AFX_MSG_MAP<CTcpseverDlg>ON_WM_SYSCOMMAND<>ON_WM_PAINT<>ON_WM_QUERYDRAGICON<>ON_WM_CLOSE<> ON_BN_CLICKED<IDC_listen,Onlisten> ON_BN_CLICKED<IDC_send,Onsend> //}}AFX_MSG_MAPEND_MESSAGE_MAP<>//CTcpseverDlgmessagehandlersBOOLCTcpseverDlg::OnInitDialog<>{ CDialog::OnInitDialog<>; //Add"About..."menuitemtosystemmenu. //IDM_ABOUTBOXmustbeinthesystemcommandrange. ASSERT<<IDM_ABOUTBOX&0xFFF0>==IDM_ABOUTBOX>; ASSERT<IDM_ABOUTBOX<0xF000>; CMenu*pSysMenu=GetSystemMenu<FALSE>; if<pSysMenu!=NULL> { CStringstrAboutMenu; strAboutMenu.LoadString<IDS_ABOUTBOX>; if<!strAboutMenu.IsEmpty<>> { pSysMenu->AppendMenu<MF_SEPARATOR>; pSysMenu->AppendMenu<MF_STRING,IDM_ABOUTBOX,strAboutMenu>; } } //Settheiconforthisdialog.Theframeworkdoesthisautomatically //whentheapplication'smainwindowisnotadialog SetIcon<m_hIcon,TRUE>; //Setbigicon SetIcon<m_hIcon,FALSE>; //Setsmallicon //TODO:Addextrainitializationhere SetDlgItemText<IDC_EDIT3,"服务器">; SetDlgItemText<IDC_EDIT4,"6666">; SetDlgItemText<IDC_EDIT2,"大家好,欢迎来到多人聊天室!!">; returnTRUE;//returnTRUEunlessyousetthefocustoacontrol}voidCTcpseverDlg::OnSysCommand<UINTnID,LPARAMlParam>{ if<<nID&0xFFF0>==IDM_ABOUTBOX> { CAboutDlgdlgAbout; dlgAbout.DoModal<>; } else { CDialog::OnSysCommand<nID,lParam>; }}//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow//todrawtheicon.ForMFCapplicationsusingthedocument/viewmodel,//thisisautomaticallydoneforyoubytheframework.voidCTcpseverDlg::OnPaint<>{ if<IsIconic<>> { CPaintDCdc<this>;//devicecontextforpainting SendMessage<WM_ICONERASEBKGND,<WPARAM>dc.GetSafeHdc<>,0>; //Centericoninclientrectangle intcxIcon=GetSystemMetrics<SM_CXICON>; intcyIcon=GetSystemMetrics<SM_CYICON>; CRectrect; GetClientRect<&rect>; intx=

温馨提示

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

评论

0/150

提交评论