(論文)vc++課程設計 聊天程序的分析與設計最新優(yōu)秀畢業(yè)論文資料搜集嘔血奉獻_第1頁
(論文)vc++課程設計 聊天程序的分析與設計最新優(yōu)秀畢業(yè)論文資料搜集嘔血奉獻_第2頁
(論文)vc++課程設計 聊天程序的分析與設計最新優(yōu)秀畢業(yè)論文資料搜集嘔血奉獻_第3頁
(論文)vc++課程設計 聊天程序的分析與設計最新優(yōu)秀畢業(yè)論文資料搜集嘔血奉獻_第4頁
(論文)vc++課程設計 聊天程序的分析與設計最新優(yōu)秀畢業(yè)論文資料搜集嘔血奉獻_第5頁
已閱讀5頁,還剩27頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

大學信電學院課程設計說明書 目錄摘要一、聊天程序的分析與設計1二、該程序的關鍵技術與算法2三、程序的實現(xiàn)33.1 項目創(chuàng)建33.2 界面設計33.3 代碼編寫5四、程序的演示結果29五、總結與致謝30六、參考文獻31摘要在這個信息爆炸的時代,人們的交往越來越依賴于一些即時的聊天程序,比如QQ、MSN等,雖然這些程序形態(tài)各異,但本質(zhì)都是一樣的。他們都是由服務器聊天程序和客戶端聊天程序組成。服務器端聊天程序接受客戶端的信息,并根據(jù)客戶端的要求把這些信息發(fā)送到另外一個客戶或多個客戶中??蛻舳藙t負責建立和維護與服務器端得連接,向服務器發(fā)送本客戶端的內(nèi)容,同時從服務器接收對方的響應??蛻舳丝梢允謩虞斎隝P地址和端口號進行連接。服務端可以手動建立服務器接受其他客戶端得連接要求。客戶端可以發(fā)送消息給服務端,顯示服務端傳來信息。服務端可以接受客戶端發(fā)送的信息,并將信息傳給所有在線的客戶端。 聊天程序的分析與設計系統(tǒng)架構方式如下圖: 客戶端 信息交互 服務器網(wǎng)卡通信底層 TCP/IPCServerSocket 通信底層 TCP/IPCClientSocket 網(wǎng)卡網(wǎng)線 1. 服務端需要完成的3件事情(1) 在特定的端口上等待來自客戶的連接請求,并且需要維護一個客戶連接表,以記錄所有成功的連接。(2) 及時接受從各個聊天客戶發(fā)送過來的信息,然后把這些信息轉發(fā)到一個或多個客戶連接。(3) 監(jiān)控這些連接的狀態(tài),在客戶主動離開或發(fā)生故障時從列表中刪除相應的表項,并及時更新連接表。2. 客戶端需要完成的3件事情(1) 建立和維護與服務器的連接,并且隨時檢測連接的狀態(tài)。(2) 把用戶輸入的信息及時發(fā)送到服務端,同時,隨時準備好接受服務端的信息,并把它顯示出來。(3) 在用戶推出聊天過程時要關閉與服務器的連接。 該程序的關鍵技術與算法MFC為套接字提供的類有CAsynSocket和CSocket,CAsynSocket提供基于異步通信的套接字封裝功能,CSocket繼承于CAsyncSocket。是Windows Socket API的高層抽樣。它通常要和CSocketFile及CArchive這兩個類混合使用。后兩個類主要負責的是數(shù)據(jù)的發(fā)送和接收。CSocket提供的通信為同步通信,數(shù)據(jù)未接收到或是未發(fā)送完之前調(diào)用不會返回。本章的聊天程序就是通過派生CSocket來完成服務端和客戶端功能。程序的實現(xiàn)3.1 項目創(chuàng)建本例將使用Visual C+6.0創(chuàng)建一個基于對話框的MFC AppWizard(exe)項目取名為“Chat”。在MFC向導的第一步界面中選擇“Dialog based”單選按鈕,在MFC AppWizard向導的第二步界面中選擇“Windows Sockets”復選框,其它均采用默認設置。3.2界面設計打開IDD_CHAT_DIALOG對話框,該對話框將是程序運行時的主界面,以下是為對話框添加的控件。如下所示: IDD_CHAT_DIALOG對話框中的主要控件 ID 屬性設置 分組框IDC_STATIC標題“” 靜態(tài)文本IDC_STATIC標題“IP地址” IP地址控件IDC_SERVERIP默認 靜態(tài)文本IDC_STATIC標題“端口” 編輯框IDC_PORT默認 分組框IDC_STATIC標題“聊天記錄” 編輯框IDC_SHOWTEXT樣式:多行,只讀 靜態(tài)文本IDC_STATIC標題“昵稱”編輯框IDC_NAME默認 命令按鈕IDC_CONNECT標題“連接服務器” 命令按鈕IDC_SETSERVER標題“建立服務器” 靜態(tài)文本框IDC_STATIC標題“消息” 編輯框IDC_INPUTTEXT默認 命令按鈕IDC_SEND標題 發(fā)送”完成控件添加后的對話框如下圖所示: 添加完上述控件后,打開Classwizard,為IDD_CHAT_DIALOG指向的CChatRoomDig類按照如下表添加成員變量。 成員變量的添加控件ID 變量名 數(shù)據(jù)類型 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實現(xiàn);CServerSocket和CClientSocket分別負責服務端和客戶端的網(wǎng)絡通信功能;CChatDig為程序的主控類,主界面、通信方式及程序邏輯均由該類實現(xiàn),它繼承自CDialog類;CMessage是對消息的封裝。CAboutDig由AppWizard實現(xiàn)。(1)CClientSocket類 本類通過相應的OnReceive消息來接受數(shù)據(jù),相應OnClose消息來斷開對話的處理。CClientSocket類實現(xiàn)了以CArchive對數(shù)據(jù)進行的串行化。事實上大多利用CSocket來傳輸數(shù)據(jù)的應用程序都會考慮到串行化的問題,因為這樣可以給數(shù)據(jù)的傳送帶來方便。 類定義代碼如下: #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)/產(chǎn)生錯誤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)/產(chǎn)生錯誤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)/產(chǎn)生錯誤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類的的主要功能是實現(xiàn)OnAccept()消息,負責監(jiān)聽服務器,是一個服務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(服務器套接字創(chuàng)建失敗!);return FALSE;if(this-Listen()=FALSE)AfxMessageBox(服務器監(jiān)聽錯誤!);return FALSE;m_dlg-SetDlgItemText(IDC_SHOWMESSAGE,服務器創(chuàng)建成功!);return TRUE;/有連接接入的時候觸發(fā)該事件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類主要作用是實現(xiàn)信息的串行化,方便信息德傳輸。其代碼如下: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();/初始化成員變量的函數(shù)void Init();/重載串行化的函數(shù),實現(xiàn)將消息串行化virtual void Serialize(CArchive& ar); ;#endifCPackMessg.cpp代碼實現(xiàn)如下:/ 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類以上三個自己添加類的具體代碼實現(xiàn),整個工程是由CChatDlg這個類來負責調(diào)度的,在基于對話框的MFC的程序中,*Dlg類是主要的實現(xiàn)類,它負責實現(xiàn)界面消息的添加和響應,組織整個工程的運行。程序運行開始,進行對話框的初始化是在OnInitDialog()函數(shù)中實現(xiàn),本程序設計成開始的時候自動獲得本地機器IP地址并顯示在IP Address Control控件中,也是在這個函數(shù)中添加如下代碼: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;/連接服務器的消息相應函數(shù)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;/建立服務器的消息相應函數(shù)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;/發(fā)送消息的按鈕的消息相應函數(shù)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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論