1、VC实现聊天室软件网络 程序设计课 程 设 计 报 告 书题 目:简单的聊天室软件 专 业:网络工程 一、题目及要求1、简单的聊天室程序本题是一个简单的聊天室程序,采用客户/服务器模式,分为客户端程序和服务器端程序。由于服务器只能支持一个客户,实际上是一个点对点通信的程序。客户端程序和服务器程序通过网络交换聊天字符串内容,并在窗口的列表框中显示。本实例程序的技术要点是:如何从CasyncSocket类派生出自己的WinSock类。理解WinSock类与应用程序框架的关系。重点学习流式套接字对象的使用。处理网络事件的方法。二,需求分析2.1 设计目的综合运用本课程及计算机网络的相关知识设计并实现
2、一个网络应用程序,以Visual C+作为开发平台,通过实践复习巩固课堂所学的理论知识,提高对所学知识的综合应用能力。2.2 设计要求 采用客户/服务器模式,分为客户端程序和服务器端程序。服务器采用WINSOCK I/O模型中的任一种,支持多个客户同时在线聊天。客户端程序和服务器程序通过网络交换聊天字符串内容,服务器窗口的列表框中显示当前在线用户,支持客户端之间的私聊(可以通过服务器中转,或考虑UDP打洞直接建立端端连接)。课程设计要求设计并编程完成两个方面的内容:首先建立一个使用TCP协议的聊天室服务器,这个服务器可以同时支持多个用户的在线聊天;其次设计一个可以和服务器通信的聊天室客户端。2
3、.3 功能要求支持多个客户端的连接,在服务器和多个客户端之间进行数据传输;接收客户端发送的消息,并显示在一个列表框中;在用户连接上后有提示,显示出连接的用户名字;发送信息时可以显示聊天的所有记录;2.4 系统主要功能和主要功能描述:服务器端聊天程序必须能够做3件事情:(1)服务器聊天程序要在待定的端口上等待来自聊天客户的连接请求,并且需要维护一个客户连接表,以记录所有成功的连接。(2)服务器聊天程序要及时接受从各个聊天客户发送过来的信息,然后把这些信息转发到一个或多个客户连接。对于公共聊天室,服务器将把接受到的信息向除源端外的所有客户发送过去。(3)服务器还要监控这些连接的状态,在客户主动离开
4、或发生故障时从列表中删除相应的表项,并及时更新连接表。这些要求可以通过CSocket类提供的功能实现。从CSocket派生出两个类CListenSocket和CClientSocket,它们分别用来侦听客户的连接请求和建立与客户的连接。服务器只需要一个侦听套接字CListenSocket,然后根据客户的连接请求动态创建客户套接字CClientSocket。客户套接字的数量是不可预知的,因此需要一个列表来记录。MFC的CPtrList类就能实现这种功能。客户端聊天程序需要完成以下几个功能:(1)客户端聊天程序要负责建立和维护与服务器的连接,通过获取用户的设置尝试与服务器的连接,并且随时检测连接的
5、状态。(2)客户端聊天程序要把用户输入的信息及时发送到聊天服务器。一般情况下,当用户输入一行信息并且按下回车键后聊天程序就要把这一行信息发送出去,才能及时地满足用户的交互需求。(3)要随时准备好接受来自服务器的信息,随时把接受到的信息显示出来,让用户及时看到对方的响应。(4)在用户退出聊天过程是要关闭与服务器的连接。比较好的做法是提前通知服务器或者直接给服务器发送一条退出通知,使得服务器能够及时掌握客户端的连接状态,把对方客户的退出信息及时发送到对等实体上。客户端聊天程序需要使用一个通过CSocket类派生出来的CChatSocket类来实现。该套接字用来发送一个与服务器的连接请求和维持与服务
6、器的连接,发送和接收聊天信息,完成上述各项功能。3设计流程图根据对用户的要求及功能设置可以得到以下的流程图3.1,用户首先启动客户端,登陆服务器并向服务器发送信息,启动服务器,服务器等待客户要求并向客户反馈在线用户信息,用户向服务器发送信息,服务器处理用户的数据,然后用户开始聊天。客户端的聊天分为对所有人的信息和私聊的信息,该信息应通过程序控制分别进行处理。图3.1 设计流程图5 设计的总结和体会该次课程设计的制作我主要是参照了图书馆内的相关书籍,找到一个类似的程序,然后按照书上的内容一步步的做出来了,虽然这个程序算不上是我自己写出来的,但通过这样的一个过程,还是让我学会了很多东西,也算能比较
7、熟练地掌握MFC这一个软件了,这算是一个不小的收获吧,而且,在做这个程序的过程中,让我认识到了在做这样程序中,遇到解决不了的问题与同学的讨论时很重要的,譬如可以以运行,但是就是无法出现连接的显示和状态。最后与同学讨论后,才知道是服务器端有了错误,没有设置自己的IP地址,然后对于客户端进行了一番修改,才终于出现了上述的结果。虽然没有彻底做的出来,但是还是比较开心的,因为自己知道了哪里不足,哪里不可以,可以在以后多多的做练习来充实自己。在课程设计过程中,收获知识,提高能力的同时,我也学到了很多人生的哲理,懂得怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪。
8、因此在以后的生活和学习的过程中,我一定会把课程设计的精神带到生活中,不畏艰难,勇往直前!我以后还是需要多多的练习,多多的勤奋,这样才有可能让自己有信心,有动力,让自己不至于懂的太少而怯场,因为不懂而不会做,相信自己以后会编写出让自己满意的程序和软件的。附:源代码I服务器:/ ServerDlg.cpp : implementation file/#include stdafx.h#include Server.h#include ServerDlg.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE
9、= _FILE_;#endif/ CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialogpublic: CAboutDlg();protected: DECLARE_MESSAGE_MAP();CAboutDlg:CAboutDlg() : CDialog(CAboutDlg:IDD)void CAboutDlg:DoDataExchange(CDataExchange* pDX) CDialog:DoDataExchange(pDX);BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)EN
10、D_MESSAGE_MAP()/ CServerDlg dialogCServerDlg:CServerDlg(CWnd* pParent /*=NULL*/) : CDialog(CServerDlg:IDD, pParent) m_hIcon = AfxGetApp()-LoadIcon(IDI_ICONAPP);void CServerDlg:DoDataExchange(CDataExchange* pDX) CDialog:DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST_USER, m_lbUser); DDX_Text(pDX, IDC
11、_EDIT_DISPLAY, m_strDisplay);BEGIN_MESSAGE_MAP(CServerDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BN_START, OnBnStart) ON_BN_CLICKED(IDC_BN_CLOSE, OnBnClose) ON_MESSAGE(WM_RECEIVE, OnReceive) ON_MESSAGE(WM_CLIENTCLOSE, OnClientClose) ON_MESSAGE(WM_ACCEPT, O
12、nAccept) ON_WM_DESTROY()END_MESSAGE_MAP()/ CServerDlg message handlersBOOL CServerDlg:OnInitDialog() CDialog:OnInitDialog(); ASSERT(IDM_ABOUTBOX & 0xFFF0) = IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR); pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); SetIcon(m_hIcon, TRUE)
13、; / Set big icon SetIcon(m_hIcon, FALSE); / Set small icon m_iNetPort = 3127; m_Server.Initialize(this); m_bServer = FALSE; GetDlgItem(IDC_BN_CLOSE)-EnableWindow(FALSE); return TRUE; / return TRUE unless you set the focus to a controlvoid CServerDlg:OnSysCommand(UINT nID, LPARAM lParam) if (nID & 0x
14、FFF0) = IDM_ABOUTBOX) CAboutDlg dlgAbout; dlgAbout.DoModal(); else CDialog:OnSysCommand(nID, lParam); void CServerDlg:OnPaint() if (IsIconic() CPaintDC dc(this); / device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); int cxIcon = GetSystemMetrics(SM_CXICON); int c
15、yIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; dc.DrawIcon(x, y, m_hIcon); else CDialog:OnPaint(); HCURSOR CServerDlg:OnQueryDragIcon() return (HCURSOR) m_hIcon;void CServerDlg:OnBnStart() / 创建
16、套接字 m_Server.Create(m_iNetPort); / 开始监听 m_Server.Listen(); / 显示 CString strInfo; strInfo.LoadString(IDS_CREATE_SERVER); ShowInDisplay(strInfo); m_bServer = TRUE; GetDlgItem(IDC_BN_START)-EnableWindow(FALSE); GetDlgItem(IDC_BN_CLOSE)-EnableWindow(TRUE);void CServerDlg:OnBnClose() CloseServer(); GetDl
17、gItem(IDC_BN_START)-EnableWindow(TRUE); GetDlgItem(IDC_BN_CLOSE)-EnableWindow(FALSE);void CServerDlg:OnAccept() / 创建新客户 CMySocket *pNewClient = new CMySocket; pNewClient-Initialize(this); m_Server.Accept(*pNewClient); / 放入链表中 m_lsClient.AddTail(pNewClient);void CServerDlg:OnClientClose(WPARAM wParam
18、, LPARAM lParam) CMySocket *p_delClient = (CMySocket*)wParam; / 关闭该用户 p_delClient-ShutDown(); char bufferBUFFERSIZE; while(p_delClient-Receive(buffer, BUFFERSIZE)0); p_delClient-Close(); / 在用户链表中删除该用户 POSITION psCur, psList = m_lsClient.GetHeadPosition(); CMySocket *p_curClient; while(psList!=NULL)
19、psCur = psList; p_curClient = (CMySocket *)m_lsClient.GetNext(psList); if(p_delClient=p_curClient) m_lsClient.RemoveAt(psCur); break; / 发送信息告诉其他用户该客户退出 CString strMsg; strMsg.LoadString(IDS_CLIENT_CLOSE); NETMESSAGE netMessage(PTC_CLIENT_QUIT, p_delClient-GetName(), _T(), p_delClient-GetName() + str
20、Msg); SendToAllClient(netMessage); / 界面上清理该用户信息 m_lbUser.DeleteString(m_lbUser.FindString(-1, p_delClient-GetName(); ShowInDisplay(p_delClient-GetName() + strMsg); / 删除该用户 delete p_delClient;void CServerDlg:OnReceive(WPARAM wParam, LPARAM lParam) CMySocket *p_curClient = (CMySocket*)wParam; NETMESSA
21、GE netMessage; p_curClient-Receive(char *)&netMessage, sizeof(netMessage); switch(netMessage.type) case PTC_NEW: / 新客户加入 NewClientAdd(p_curClient, &netMessage); break; case PTC_SAY: / 普通聊天 ShowMessage(netMessage); break; / 把加工过的信息发送给其他用户 SendToAllClient(netMessage);void CServerDlg:CloseServer() if(!
22、m_bServer) return; / 向所有客户发送服务端关闭的信息 CString strInfo; strInfo.LoadString(IDS_CLOSESERVER); NETMESSAGE netMessage(PTC_SYSTEM, _T(), _T(), strInfo); SendToAllClient(netMessage); / 服务端界面显示关闭信息 ShowInDisplay(strInfo); / 关闭服务端 m_Server.Close(); / 关闭客户端 char bufferBUFFERSIZE; CMySocket *m_pClient; POSITIO
23、N psList = m_lsClient.GetHeadPosition(); while(psList!=NULL) m_pClient = (CMySocket *)m_lsClient.GetNext(psList); m_pClient-ShutDown(); while(m_pClient-Receive(buffer, BUFFERSIZE)0); m_pClient-Close(); delete m_pClient; m_lsClient.RemoveAll(); m_bServer = FALSE;/ 向所有户发出信息void CServerDlg:SendToAllCli
24、ent(const NETMESSAGE &netMessage) CMySocket *m_pClient; POSITION psList = m_lsClient.GetHeadPosition(); while(psList!=NULL) m_pClient = (CMySocket *)m_lsClient.GetNext(psList); m_pClient-SendMsg(netMessage); void CServerDlg:ShowInDisplay(CString str) m_strDisplay += str + rn; UpdateData(false);void
25、CServerDlg:OnDestroy() CDialog:OnDestroy(); / TODO: Add your message handler code here/ 新用户加入 void CServerDlg:NewClientAdd(CMySocket *p_client, NETMESSAGE *netMessage) / 存入用户名字 p_client-SetName(netMessage-form); / 在列表框中显示该用户 m_lbUser.AddString(p_client-GetName(); / 发送用户列表给该客户 NETMESSAGE netMsg(PTC_U
26、SER_LIST, _T(), _T(), _T(); int iListLen = m_lbUser.GetCount(); CString strMsg; for(int index=m_lbUser.GetTopIndex(); indexSendMsg(netMsg); / 加工信息 strMsg.LoadString(IDS_NEW_CLIENT); strMsg = p_client-GetName() + strMsg; strcpy(netMessage-data, (LPCTSTR)strMsg); / 显示该用户进入 ShowInDisplay(strMsg);/ 显示普通
27、消息void CServerDlg:ShowMessage(NETMESSAGE netMessage) CString strTo = netMessage.to; if(strTo=_T() strTo = 所有人; CString strForm = netMessage.form; CString strMsg = netMessage.data; CString strOut = strForm + 对 + strTo + 说: + strMsg; ShowInDisplay(strOut);II客户端:/ ClientDlg.cpp : implementation file/#include stdafx.h#include Client.h#include ClientDlg.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialogpublic: CAboutDlg(); enum IDD = IDD_ABOUTBOX ; protected: virtual void DoDataExchange
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1