(论文)vc++课程设计 聊天程序的分析与设计最新优秀毕业论文资料搜集呕血奉献_第1页
(论文)vc++课程设计 聊天程序的分析与设计最新优秀毕业论文资料搜集呕血奉献_第2页
(论文)vc++课程设计 聊天程序的分析与设计最新优秀毕业论文资料搜集呕血奉献_第3页
(论文)vc++课程设计 聊天程序的分析与设计最新优秀毕业论文资料搜集呕血奉献_第4页
(论文)vc++课程设计 聊天程序的分析与设计最新优秀毕业论文资料搜集呕血奉献_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

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

文档简介

大学信电学院课程设计说明书 目录摘要一、聊天程序的分析与设计1二、该程序的关键技术与算法2三、程序的实现33.1 项目创建33.2 界面设计33.3 代码编写5四、程序的演示结果29五、总结与致谢30六、参考文献31摘要在这个信息爆炸的时代,人们的交往越来越依赖于一些即时的聊天程序,比如QQ、MSN等,虽然这些程序形态各异,但本质都是一样的。他们都是由服务器聊天程序和客户端聊天程序组成。服务器端聊天程序接受客户端的信息,并根据客户端的要求把这些信息发送到另外一个客户或多个客户中。客户端则负责建立和维护与服务器端得连接,向服务器发送本客户端的内容,同时从服务器接收对方的响应。客户端可以手动输入IP地址和端口号进行连接。服务端可以手动建立服务器接受其他客户端得连接要求。客户端可以发送消息给服务端,显示服务端传来信息。服务端可以接受客户端发送的信息,并将信息传给所有在线的客户端。 聊天程序的分析与设计系统架构方式如下图: 客户端 信息交互 服务器网卡通信底层 TCP/IPCServerSocket 通信底层 TCP/IPCClientSocket 网卡网线 1. 服务端需要完成的3件事情(1) 在特定的端口上等待来自客户的连接请求,并且需要维护一个客户连接表,以记录所有成功的连接。(2) 及时接受从各个聊天客户发送过来的信息,然后把这些信息转发到一个或多个客户连接。(3) 监控这些连接的状态,在客户主动离开或发生故障时从列表中删除相应的表项,并及时更新连接表。2. 客户端需要完成的3件事情(1) 建立和维护与服务器的连接,并且随时检测连接的状态。(2) 把用户输入的信息及时发送到服务端,同时,随时准备好接受服务端的信息,并把它显示出来。(3) 在用户推出聊天过程时要关闭与服务器的连接。 该程序的关键技术与算法MFC为套接字提供的类有CAsynSocket和CSocket,CAsynSocket提供基于异步通信的套接字封装功能,CSocket继承于CAsyncSocket。是Windows Socket API的高层抽样。它通常要和CSocketFile及CArchive这两个类混合使用。后两个类主要负责的是数据的发送和接收。CSocket提供的通信为同步通信,数据未接收到或是未发送完之前调用不会返回。本章的聊天程序就是通过派生CSocket来完成服务端和客户端功能。程序的实现3.1 项目创建本例将使用Visual C+6.0创建一个基于对话框的MFC AppWizard(exe)项目取名为“Chat”。在MFC向导的第一步界面中选择“Dialog based”单选按钮,在MFC AppWizard向导的第二步界面中选择“Windows Sockets”复选框,其它均采用默认设置。3.2界面设计打开IDD_CHAT_DIALOG对话框,该对话框将是程序运行时的主界面,以下是为对话框添加的控件。如下所示: IDD_CHAT_DIALOG对话框中的主要控件 ID 属性设置 分组框IDC_STATIC标题“” 静态文本IDC_STATIC标题“IP地址” IP地址控件IDC_SERVERIP默认 静态文本IDC_STATIC标题“端口” 编辑框IDC_PORT默认 分组框IDC_STATIC标题“聊天记录” 编辑框IDC_SHOWTEXT样式:多行,只读 静态文本IDC_STATIC标题“昵称”编辑框IDC_NAME默认 命令按钮IDC_CONNECT标题“连接服务器” 命令按钮IDC_SETSERVER标题“建立服务器” 静态文本框IDC_STATIC标题“消息” 编辑框IDC_INPUTTEXT默认 命令按钮IDC_SEND标题 发送”完成控件添加后的对话框如下图所示: 添加完上述控件后,打开Classwizard,为IDD_CHAT_DIALOG指向的CChatRoomDig类按照如下表添加成员变量。 成员变量的添加控件ID 变量名 数据类型 IDC_PORT m_uport UNIT IDC_ SHOWTEXT m_sShowString CString IDC_NAME m_sName CString IDC_INPUTTEXT m_sInputText CString 3.3 代码编写聊天程序一共有6个类,其中CChatApp由AppWiardS实现;CServerSocket和CClientSocket分别负责服务端和客户端的网络通信功能;CChatDig为程序的主控类,主界面、通信方式及程序逻辑均由该类实现,它继承自CDialog类;CMessage是对消息的封装。CAboutDig由AppWizard实现。(1)CClientSocket类 本类通过相应的OnReceive消息来接受数据,相应OnClose消息来断开对话的处理。CClientSocket类实现了以CArchive对数据进行的串行化。事实上大多利用CSocket来传输数据的应用程序都会考虑到串行化的问题,因为这样可以给数据的传送带来方便。 类定义代码如下: #include PackMessg.h/ CClientSocket command targetclass CChatDlg;class CClientSocket : public CSocket/ Attributespublic:CArchive* m_aSessionIn;CArchive* m_aSessionOut;CSocketFile* m_sfSocketFile; CChatDlg * m_dlg;bool m_bInit; /作为套接字是否被初始化的标记bool m_bClose; /作为套接字是否被关闭的标记/ Operationspublic:void Init(CChatDlg * dlg);BOOL SendMessage(CPackMessg * msg);void CloseSocket();public:static int GetLocalHostName(CString &sHostName);/获得本地计算机名称static int GetIpAddress(const CString &sHostName, CString &sIpAddress);/获得本地IPstatic int GetIpAddress(const CString &sHostName, BYTE &f0,BYTE &f1,BYTE &f2,BYTE &f3);/获得本地IPstatic CString ErrorReason(int tag);public:CClientSocket();virtual CClientSocket();在CClientSocket.cpp文件中添加的代码如下:#include stdafx.h#include chatzyj.h#include ClientSocket.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CClientSocketCClientSocket:CClientSocket()m_aSessionIn=NULL;m_aSessionOut=NULL;m_sfSocketFile=NULL;m_bInit=false;m_bClose=false;CClientSocket:CClientSocket() if(m_aSessionIn)delete m_aSessionIn;if(m_aSessionOut)delete m_aSessionOut;if(m_sfSocketFile)delete m_sfSocketFile;/ Do not edit the following lines, which are needed by ClassWizard.#if 0BEGIN_MESSAGE_MAP(CClientSocket, CSocket)/AFX_MSG_MAP(CClientSocket)/AFX_MSG_MAPEND_MESSAGE_MAP()#endif/ 0/ CClientSocket member functionsvoid CClientSocket:OnReceive(int nErrorCode) / TODO: Add your specialized code here and/or call the base classCSocket:OnReceive(nErrorCode);doCPackMessg temp;temp.Serialize(*m_aSessionIn);m_dlg-m_sMsgList+=temp.m_strText+rn;m_dlg-SetDlgItemText(IDC_SHOWMESSAGE,m_dlg-m_sMsgList);int linenum=(CEdit *)(m_dlg-GetDlgItem(IDC_SHOWMESSAGE)-GetLineCount();(CEdit *)(m_dlg-GetDlgItem(IDC_SHOWMESSAGE)-LineScroll(linenum);if(!m_dlg-m_bClient)for(POSITION pos=m_dlg-m_connectionList.GetHeadPosition();pos!=NULL;)CClientSocket*t=(CClientSocket*)m_dlg-m_connectionList.GetNext(pos);if(t-m_hSocket!=this-m_hSocket)t-SendMessage(&temp);while (!m_aSessionIn-IsBufferEmpty();void CClientSocket:OnClose(int nErrorCode) / TODO: Add your specialized code here and/or call the base classCSocket:OnClose(nErrorCode);m_bClose=true;CloseSocket();m_dlg-CloseSessionSocket();CSocket:OnClose(nErrorCode);void CClientSocket:Init(CChatDlg * dlg)m_sfSocketFile= new CSocketFile(this);m_aSessionIn=new CArchive(m_sfSocketFile,CArchive:load);m_aSessionOut=new CArchive(m_sfSocketFile,CArchive:store);m_bClose=false;this-m_dlg=dlg;BOOL CClientSocket:SendMessage(CPackMessg * msg)if (m_aSessionOut != NULL)msg-Serialize(*m_aSessionOut);m_aSessionOut-Flush();return TRUE;else/对方关闭了连接m_bClose=true;CloseSocket();m_dlg-CloseSessionSocket();return FALSE;void CClientSocket:CloseSocket()if(m_aSessionIn)delete m_aSessionIn;m_aSessionIn=NULL;if(m_aSessionOut)delete m_aSessionOut;m_aSessionOut=NULL;if(m_sfSocketFile)delete m_aSessionOut;m_sfSocketFile=NULL;Close();m_bInit=false;m_bClose=true;int CClientSocket:GetLocalHostName(CString &sHostName)/获得本地计算机名称char szHostName256;int nRetCode;nRetCode=gethostname(szHostName,sizeof(szHostName);if(nRetCode!=0)/产生错误sHostName=_T(没有取得);return GetLastError();sHostName=szHostName;return 0;int CClientSocket:GetIpAddress(const CString &sHostName, CString &sIpAddress)/获得本地IPstruct hostent FAR * lpHostEnt=gethostbyname(sHostName);if(lpHostEnt=NULL)/产生错误sIpAddress=_T();return GetLastError();/获取IPLPSTR lpAddr=lpHostEnt-h_addr_list0;if(lpAddr)struct in_addr inAddr;memmove(&inAddr,lpAddr,4);/转换为标准格式sIpAddress=inet_ntoa(inAddr);if(sIpAddress.IsEmpty()sIpAddress=_T(没有取得);return 0;int CClientSocket:GetIpAddress(const CString &sHostName, BYTE &f0,BYTE &f1,BYTE &f2,BYTE &f3)/获得本地IPstruct hostent FAR * lpHostEnt=gethostbyname(sHostName);if(lpHostEnt=NULL)/产生错误f0=f1=f2=f3=0;return GetLastError();/获取IPLPSTR lpAddr=lpHostEnt-h_addr_list0;if(lpAddr)struct in_addr inAddr;memmove(&inAddr,lpAddr,4);f0=inAddr.S_un.S_un_b.s_b1;f1=inAddr.S_un.S_un_b.s_b2;f2=inAddr.S_un.S_un_b.s_b3;f3=inAddr.S_un.S_un_b.s_b4;return 0;CString CClientSocket:ErrorReason(int tag)CString result;switch(tag)case WSANOTINITIALISED:result=A successful AfxSocketInit must occur before using this API.;break;case WSAENETDOWN:result=the network subsystem failed;break;case WSAEADDRINUSE:result=The specified address is already in use;break;case WSAEINPROGRESS:result=A blocking Windows Sockets call is in progress;break;case WSAEADDRNOTAVAIL:result=The specified address is not available from the local machine;break;case WSAEAFNOSUPPORT:result=Addresses in the specified family cannot be used with this socket;break;case WSAECONNREFUSED:result=The attempt to connect was rejected;break;case WSAEDESTADDRREQ:result=A destination address is required;break;case WSAEFAULT:result=The nSockAddrLen argument is incorrect;break;case WSAEINVAL:result=Invalid host address;break;case WSAEISCONN:result=The socket is already connected.;break;case WSAEMFILE:result=No more file descriptors are available;break;case WSAENETUNREACH:result=The network cannot be reached from this host at this time;break;case WSAENOBUFS:result=No buffer space is available. The socket cannot be connected;break;case WSAENOTSOCK:result=The descriptor is not a socket;break;case WSAETIMEDOUT:result=Attempt to connect timed out without establishing a connection;break;case WSAEWOULDBLOCK:result=The socket is marked as nonblocking and the connection cannot be completed immediately.;break;default:result=unknown error;return result;(2) CServerSocket类CServerSocket类的的主要功能是实现OnAccept()消息,负责监听服务器,是一个服务Socket。其文件的代码如下:/ ServerSocket.cpp : implementation file/#include stdafx.h#include chat.h#include ServerSocket.h#include chatDlg.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CServerSocket/ Do not edit the following lines, which are needed by ClassWizard.#if 0BEGIN_MESSAGE_MAP(CServerSocket, CSocket)/AFX_MSG_MAP(CServerSocket)/AFX_MSG_MAPEND_MESSAGE_MAP()#endif/ 0/ CServerSocket member functionsBOOL CServerSocket:Init(UINT port, CChatDlg* dlg)m_uPort=port;m_dlg=dlg;if(Create(m_uPort)=FALSE)AfxMessageBox(服务器套接字创建失败!);return FALSE;if(this-Listen()=FALSE)AfxMessageBox(服务器监听错误!);return FALSE;m_dlg-SetDlgItemText(IDC_SHOWMESSAGE,服务器创建成功!);return TRUE;/有连接接入的时候触发该事件void CServerSocket:OnAccept(int nErrorCode) / TODO: Add your specialized code here and/or call the base classm_dlg-ProcessPendingAccept();CSocket:OnAccept(nErrorCode); (3) CMessage类 CPackMessg类主要作用是实现信息的串行化,方便信息德传输。其代码如下:CPackMessg.h文件的代码如下:/ PackMessg.h: interface for the CPackMessg class./#if !defined(AFX_PACKMESSG_H_DF511BFD_1563_412D_85B5_EF323A3074EF_INCLUDED_)#define AFX_PACKMESSG_H_DF511BFD_1563_412D_85B5_EF323A3074EF_INCLUDED_#if _MSC_VER 1000#pragma once#endif / _MSC_VER 1000class CPackMessg :public CObjectpublic:CString m_strText;public:CPackMessg();virtual CPackMessg();/初始化成员变量的函数void Init();/重载串行化的函数,实现将消息串行化virtual void Serialize(CArchive& ar); ;#endifCPackMessg.cpp代码实现如下:/ PackMessg.cpp: implementation of the CPackMessg class./#include stdafx.h#include chat.h#include PackMessg.h#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE=_FILE_;#define new DEBUG_NEW#endif/ Construction/Destruction/CPackMessg:CPackMessg()Init();void CPackMessg:Init()m_strText = _T();/ CMsg serializationvoid CPackMessg:Serialize(CArchive& ar)if (ar.IsStoring()ar m_strText;(4) CChatDig类以上三个自己添加类的具体代码实现,整个工程是由CChatDlg这个类来负责调度的,在基于对话框的MFC的程序中,*Dlg类是主要的实现类,它负责实现界面消息的添加和响应,组织整个工程的运行。程序运行开始,进行对话框的初始化是在OnInitDialog()函数中实现,本程序设计成开始的时候自动获得本地机器IP地址并显示在IP Address Control控件中,也是在这个函数中添加如下代码:BOOL CChatDlg:OnInitDialog()CDialog:OnInitDialog();/ Add About. menu item to system menu./ IDM_ABOUTBOX must be in the system command range.ASSERT(IDM_ABOUTBOX & 0xFFF0) = IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR);pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);/ Set the icon for this dialog. The framework does this automatically/ when the applications main window is not a dialogSetIcon(m_hIcon, TRUE);/ Set big iconSetIcon(m_hIcon, FALSE);/ Set small icon/ TODO: Add extra initialization here/自行添加的程序代码,目的是在初始化对话框的时候就自动显示出本地的ip地址if(AfxSocketInit(NULL)=0)AfxMessageBox(CSocket 初始化失败!);BYTE f0,f1,f2,f3;CString name;CClientSocket:GetLocalHostName(name);CClientSocket:GetIpAddress(name,f0,f1,f2,f3);(CIPAddressCtrl *)(GetDlgItem(IDC_IPADDRESS)-SetAddress(f0,f1,f2,f3);m_bInit=false;m_bClient=false;return TRUE; / return TRUE unless you set the focus to a controlvoid CChatDlg:OnSysCommand(UINT nID, LPARAM lParam)if (nID & 0xFFF0) = IDM_ABOUTBOX)CAboutDlg dlgAbout;dlgAbout.DoModal();elseCDialog:OnSysCommand(nID, lParam);/ If you add a minimize button to your dialog, you will need the code below/ to draw the icon. For MFC applications using the document/view model,/ this is automatically done for you by the framework.void CChatDlg:OnPaint() if (IsIconic()CPaintDC dc(this); / device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);/ Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;/ Draw the icondc.DrawIcon(x, y, m_hIcon);else:OnPaint();/ The system calls this to obtain the cursor to display while the user drags/ the minimized window.HCURSOR CChatDlg:OnQueryDragIcon()return (HCURSOR) m_hIcon;/连接服务器的消息相应函数void CChatDlg:OnConnect() / TODO: Add your control notification handler code hereif(!m_bInit)BYTE f0,f1,f2,f3;CString name;(CIPAddressCtrl *)(GetDlgItem(IDC_IPADDRESS)-GetAddress(f0,f1,f2,f3);CString ip;ip.Format(%d.%d.%d.%d,f0,f1,f2,f3);m_bClient=true;m_clientsocket.Create();if(m_clientsocket.Connect(ip,GetDlgItemInt(IDC_PORT)m_clientsocket.Init(this);SetDlgItemText(IDC_SHOWMESSAGE,客户端连接成功!);m_bInit=true;elsem_clientsocket.Close();AfxMessageBox(客户端连接失败!);m_bInit=false;/建立服务器的消息相应函数void CChatDlg:OnSetserver() / TODO: Add your control notification handler code hereif(!m_bInit)m_bClient=false;m_bInit=true;if(m_pListenSocket.Init(GetDlgItemInt(IDC_PORT),this)=FALSE)m_bInit=false;return;/发送消息的按钮的消息相应函数void CChatDlg:OnSend() / TODO: Add your control notification handler code hereif(!m_bInit)AfxMessageBox(没有和服务器建立连接!);return;CString in;CPackMessg msg;GetDlgItemText(IDC_MESSAGE,in);GetDlgItemText(IDC_NAME,m_strName);if(in.GetLength()2) m_sMsgList+=m_strName+说:;m_sMsgList+=in+rn;SetDlgItemText(IDC_SHOWMESSAGE,m_sMsgList);int m_iLineCurrentPos=(CEdit *)(GetDlgItem(IDC_SHOWMESSAGE)-GetLineCount();(CEdit *)(GetDlgItem(IDC_SHOWMESSAGE)-LineScroll(m_iLineCurrentPos);msg.m_strText=m_strName+说:+in;if(!m_bClient)POSITION pos;for(pos=m_connectionList.GetHeadPosition();pos!=NULL;)CClientSocket * t= (CClientSocket *)m_connectionList.GetNext(pos);t-SendMessage(&msg);elsem_clientsocket.SendMessage(&msg);void CChatDlg:ProcessPendingAccept()CClientSocket* pSocket = new CClientSocket();if (m_pListenSocket.Accept(*pSocket)CPackMessg msg;msg.m_strText=一个游客进入聊天室了;m_strShowMessage+=一个游客进入聊天室了n;SetDlgItemText(IDC_SHOWMESSAGE,一个游客进入聊天室了n);POSITION pos;for(pos=m_connectionList.GetHeadPosition();pos!=NULL;)CClientSocket * t= (CClientSocket *)m_connectionList.GetNext(pos);t-SendMessage(&msg);pSocket-Init(this);m_connectionList.AddTail(pSocket);elsedelete pSocket;void CChatDlg:ClearContent()if(m_bClient)m_clientsocket.Close();elsem_pListenSocket.Close();m_connectionList.RemoveAll();m_bInit=false;m_sMsgList=;SetDlgItemText(IDC_MESSAGE,);SetDlgItemText(IDC_SHOWMESSAGE,);void CChatDlg:OnClearconnection() ClearContent();void CChatDlg:CloseSessionSocket()if(!m_bClient)for(POSITION pos=m_connectionList.GetHeadPosition();pos!=NULL;)POSITION t_pos=pos;CClientSocket * t = (CClientSocket*)m_connectionList.GetNext(pos);if(t-m_bClose=true)m_connectionList.RemoveAt(t_pos);ChatDlg.h文件的代码:#pragma once#endif / _MSC_VER 1000#include ServerSocket.h#include ClientSocket.h/ CChatDlg dialogclass CChatDlg : public CDialog/ Constructionpublic:CChatDlg(CWnd* pParent = NULL);/ standard constructor/ Dialog Data/AFX_DATA(CChatDlg)e

温馨提示

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

评论

0/150

提交评论