版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Windows系统编程课程设计计算机科学学院08级自动化一班08064021刘欣然Windows系统编程课程设计计算机科学学院08级自动化一班08064021刘欣然 中南民族大学计算机科学学院Windows系统编程课程设计报告题目:简易聊天室程序之服务器系统专业自动化学生姓名刘欣然班级学号自动化1班08064021完成日期2010.12.30课题名称简易聊天室程序之服务器系统二、课题内容和要求1、内容:了解Windows编程的基础知识,掌握MFC应用程序的基本知识加深对数据库的掌握和运用掌握用VC++开发应用程序的的一般步骤和方法进一步加强C++的编程能力和对程序结构的理解5.基本掌握面向对象程序设计的基本思路和方法2.要求:运用MFC编程方法制作一个简单网络聊天室的系统,可以自定义服务器端口,即时显示在线好友的IP地址,在服务器上显示好友的上线下线信息,显示在线好友发送消息的内容、具体时间,显示并可以向客户端发送信息。了解Windows编程的基础知识,掌握MFC应用程序的基本知识;基本掌握面向对象程序设计的基本思路和方法;掌握用VC++开发应用程序的一般步骤和方法;系统以Windows标准菜单界面方式工作,运行界面友好,演示程序以用户和计算机的对话方式进行程序的功能建立一个基于对话框的MFC,要设置权限,即设置一个登陆的对话框。进入系统以后能够展示出一个普通的汽车公司售票系统,能够实现售票等基本功能。输入输出的要求采用界面选择与编辑框两种输入方式,输出结果直接显示在售票对话框中。输入的数据必须符合程序所规定的合法输入方式,对不合法的信息输入将提示无法处理。4.综合应用使用界面编程、网络、数据库、文件系统、线程和进程、异常处理等知识。特别是数据库的应用,用来存储数据和提供数据。对于网络主要进行网络通信,连接客户端和服务器端。采取模块化方式进行程序设计,要求程序的功能设计、数据结构设计及整体结构设计合理三、开发工具介绍随着计算机的广泛应用,办公无纸化正在越来越普及,传统的手工信息管理已显然不能满足人们的需求,这就需要一种适应潮流的新的管理系统的出现,员工信息管理与考勤系统就是用VisualC++开发的Access数据库管理系统。
Access数据库是一个关系数据库,在VisualC++中,可以用SQL语句实现对它的操作。本系统的建表是直接在Access中进行,而对表的操作则在VisualC++中通过编程进行。VisualC++是一种编程开发非常灵活的工具。有两种编程方法:其一是WINDOWS
API函数,另一种就是使用MFC。VisualC++与数据库连接的一种方式是MFCODBC连接VisualStudio2010是微软亚太研发集团服务器与开发工具事业部成立以来参与的最大开发项目。超过100位工程师在为VisualStudio2010的多个重要模块设计中贡献了他们的智慧与心血。在.NETFramework4.0中为WindowsForms架构设计运行时和设计时的新功能;对SharePoint、Silverlight、WPF、WCF、WF等多个平台提供更多工具支持;大大增强VisualStudio中的各种基本开发工具,例如C++编译和链接工具,并行开发工具中的调试器和性能探视器;为更好地支持团队开发,提供全新的UML建模工作组件、模型浏览器和建模工程等。Microsoft为单独工作或在小型团队中的专业开发人员提供了两种选择,VisualStudio2005ProfessionalEdition和用于MicrosoftOffice系统的VisualStudio2005工具。每种版本都在标准版的特性上进行了扩展,包括用于远程服务程序开发和调试、SQLServer2005开发的工具,以及完整的、没有限制的开发环境。每种产品都可以单独购买或打包定购。专业开发人员喜欢自由的使用.NETFramework2.0,它是一种稳健的、功能齐备的开发环境,支持创建扩展VisualStudio集成开发环境的工具。MFC借助C++的优势为Windows开发开辟了一片新天地,同时也借助ApplicationWizzard使开发者摆脱离了那些每次都必写基本代码,借助ClassWizard和消息映射使开发者摆脱了定义消息处理时那种混乱和冗长的代码段。更令人兴奋的是利用C++的封装功能使开发者摆脱Windows中各种句柄的困扰,只需要面对C++中的对象,这样一来使开发更接近开发语言而远离系统.利用C++的封装性开发者可以更容易理解和操作各种窗口对象;利用C++的派生性开发者可以减少开发自定义窗口的时间和创造出可重用的代码;利用虚拟性可以在必要时更好的控制窗口的活动。而且C++本身所具备的超越C语言的特性都可以使开发者编写出更易用,更灵活的代码。PlatformSDK。这才是VisualC++和整个VisualStudio的精华和灵魂,虽然我们很少能直接接触到它。大致说来,PlatformSDK是以MicrosoftC/C++编译器为核心(不是VisualC++,看清楚了),配合MASM,辅以其他一些工具和文档资料。上面说到DeveloperStudio没有编译程序的功能,那么这项工作是由谁来完成的呢?是CL,是NMAKE,和其他许许多多命令行程序,这些我们看不到的程序才是构成VisualStudio的基石。vc++是Windows平台上的C++编程环境,学习VC要了解很多Windows平台的特性并且还要掌握MFC、ATL、COM等的知识,难度比较大。Windows下编程需要了解Windows的消息机制以及回调(callback)函数的原理;MFC是Win32API的包装类,需要理解文档视图类的结构,窗口类的结构,消息流向等等;COM是代码共享的二进制标准,需要掌握其基本原理等等。VC作为一个主流的开发平台一直深受编程爱好者的喜爱,但是很多人却对它的入门感到难于上青天,究其原因主要是大家对他错误的认识造成的,严格的来说VC++不是门语言,虽然它和C++之间有密切的关系,如果形象点比喻的话,可以C++看作为一种”工业标准”,而VC++则是某种操作系统平台下的”厂商标准”,而”厂商标准”是在遵循”工业标准”的前提下扩展而来的。
VC++应用程序的开发主要有两种模式,一种是WINAPI方式,另一种则是MFC方式,传统的WINAPI开发方式比较繁琐,而MFC则是对WINAPI再次封装,所以MFC相对于WINAPI开发更具备效率优势。Windows系统是一个消息驱动的OS:1、消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。2、谁将收到消息:一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。3、未处理的消息到那里去了:M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。4、窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二。设计思路模拟QQ聊天室系统,制作一个服务器对话框,当客户端A登陆或下线时,显示A上线下线的消息以及具体时间,A发送消息时,显示消息的内容和具体的时间。并可以转发A消息的内容。服务器本身也能发送消息,显示消息内容及具体时间。计算机网络技术发展至今已经大大超越了人们当初的预想,无论是人们日常的工作还是学习,我们都越来越多的依靠到互联网。各种实时性的聊天娱乐软件也同时诞生,而且为我们的即时通讯带来了众多的方便,比如说大家所熟知的腾讯QQ、微软的MSN、移动的Fetion等,都是做的比较成功的实时聊天工具。随着网络的日益普及,各种聊天工具也层出不穷,但当我们学习了《TCP/IP协议与网络编程》这门课程之后,我们便会觉得,其实要实现简单的网络通讯其实并不难。接下来的课程设计就是针对一个简单的网络聊天程序,利用MFC为开发工具,实现基本的通讯功能。此程序主要分为两部分:服务器端和客户端。服务器端用于提供一个网络端口,等待客户端发出请求,登录到此服务端,然后进行网络通讯和消息的转发;客户端可通过服务器端的IP地址发送连接请求,然后登陆聊天室。在服务器端的成员列表栏中会显示在线的所有人名单,有人退出聊天室,成员列表会自动除名。服务器端同时也提供了成员之间的私聊功能,此时服务器端作为一个转发站,进行消息的转发。整个程序的主体使用了CSocket类的方法,实现了网络通讯聊天。整个程序设计为两个部分:服务器(ChatRoomServer)和客户端(ChatRoom)多人聊天的关键在于要将每个客户端发送过来的消息分发给所有其他客户端,为了解决这个问题,在服务器程序中建立一个套接口链表,用来保存所有与客户端建立了连接的服务端口。下面描述了多人聊天的实现原理:当客户端ClientN向对应的服务端口N发送了消息Message,服务端口N将Message复制给所有套接口列表(USERLIST)中的套接口缓冲区,然后向每个服务端口发送WRITE消息,使每个服务端口将Message发送给对应的客户端。这样,所有客户端就都获得了Message消息,实现了多人聊天功能。BOOLCClientSocketList::Sends(char*buff,intn){CClientSocket*curr=Head; while(curr) {curr->Send(buff,n); curr=curr->Next;} returntrue;}USERLIST表时多人聊天程序的核心,它是一个动态变化的链表,为空表示没有客户端建立了连接,不为空时每个元素就代表有一个客户端与服务器建立了连接。以下程序是私聊功能的实现:BOOLCClientSocketList::OnlySend(char*buff,intn,intwho){ CClientSocket*curr=Head; while(curr&&who>0) {curr=curr->Next; who--;} curr->Send(buff,n); returntrue;}五、流程图(或功能模块图)开始开始开始绑定绑定是否成功?开始侦听启动线程判断是否有客户端连接?获取客户端数量,向每个连接客户端循环发送和接收信息判断哪一个客户端断开连接?停止对该客户端发送和接收消息结束是否是否测试数据及其结果分析WINDOWS环境下有三个客户端,分别是老师、刘欣然、谭斌文,和一个服务器,他们互相通信的结果在服务器对话框显示如下:客户端刘欣然登陆成功:七、调试过程中的问题程序详细设计//服务器Dlg.cpp:实现文件//#include"stdafx.h"#include"服务器.h"#include"服务器Dlg.h"#include"afxdialogex.h"#include<io.h>#ifdef_DEBUG#definenewDEBUG_NEW#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endif//用于应用程序“关于”菜单项的CAboutDlg对话框classCAboutDlg:publicCDialogEx{public: CAboutDlg();//对话框数据 enum{IDD=IDD_ABOUTBOX}; protected: virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDV支持//实现protected: DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg():CDialogEx(CAboutDlg::IDD){}voidCAboutDlg::DoDataExchange(CDataExchange*pDX){ CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg,CDialogEx)END_MESSAGE_MAP()//C服务器Dlg对话框C服务器Dlg::C服务器Dlg(CWnd*pParent/*=NULL*/) :CDialogEx(C服务器Dlg::IDD,pParent){ m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);}voidC服务器Dlg::DoDataExchange(CDataExchange*pDX)//给变量赋相应控件的ID值{ CDialogEx::DoDataExchange(pDX); DDX_Control(pDX,IDC_EDIT1,m_edit1); DDX_Control(pDX,IDC_EDIT2,m_edit2); DDX_Control(pDX,IDC_BUTTON1,m_button); DDX_Control(pDX,IDC_LIST1,m_list); }BEGIN_MESSAGE_MAP(C服务器Dlg,CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1,&C服务器Dlg::OnBnClickedButton1) ON_BN_CLICKED(IDCANCEL,&C服务器Dlg::OnBnClickedCancel) ON_EN_CHANGE(IDC_EDIT2,&C服务器Dlg::OnEnChangeEdit2)END_MESSAGE_MAP()//C服务器Dlg消息处理程序BOOLC服务器Dlg::OnInitDialog(){ CDialogEx::OnInitDialog(); //将“关于...”菜单项添加到系统菜单中。 //IDM_ABOUTBOX必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX<0xF000); CMenu*pSysMenu=GetSystemMenu(FALSE); if(pSysMenu!=NULL) { BOOLbNameValid; CStringstrAboutMenu; bNameValid=strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if(!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu); } } //设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 //执行此操作 SetIcon(m_hIcon,TRUE); //设置大图标 SetIcon(m_hIcon,FALSE); //设置小图标 //TODO:在此添加额外的初始化代码 count=0; m_list.InsertColumn(0,"消息");//消息栏 m_list.SetColumnWidth(0,435);//设置消息输出框的初始位置和宽度 m_edit1.SetLimitText(99);//限制消息输入框的输入字符 m_edit2.SetWindowText("服务器");//初始化用户姓名框 for(inti=0;i<50;i++)// msgsock[i]=NULL; //设定地址 serv.sin_addr.s_addr=htonl(INADDR_ANY);//储存任何IP地址 serv.sin_family=AF_INET; serv.sin_port=5000;//设置端口为(5000); addlen=sizeof(serv); m_button.EnableWindow(FALSE); //创建socket sock=socket(AF_INET,SOCK_STREAM,0); //绑定 if(bind(sock,(sockaddr*)&serv,addlen)) { m_edit1.SetWindowText("绑定错误"); } else { //m_list.InsertItem(count++,inet_ntoa(serv.sin_addr)); m_edit1.SetWindowText("服务器创建成功"); //开始侦听 listen(sock,5);//设置最多能侦听5个线程 AfxBeginThread(&thread,0);//调用线程 } returnTRUE;//除非将焦点设置到控件,否则返回TRUE}voidC服务器Dlg::OnSysCommand(UINTnID,LPARAMlParam){ if((nID&0xFFF0)==IDM_ABOUTBOX) { CAboutDlgdlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID,lParam); }}//如果向对话框添加最小化按钮,则需要下面的代码//来绘制该图标。对于使用文档/视图模型的MFC应用程序,//这将由框架自动完成。voidC服务器Dlg::OnPaint(){ if(IsIconic()) { CPaintDCdc(this);//用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND,reinterpret_cast<WPARAM>(dc.GetSafeHdc()),0); //使图标在工作区矩形中居中 intcxIcon=GetSystemMetrics(SM_CXICON); intcyIcon=GetSystemMetrics(SM_CYICON); CRectrect; GetClientRect(&rect); intx=(rect.Width()-cxIcon+1)/2; inty=(rect.Height()-cyIcon+1)/2; //绘制图标 dc.DrawIcon(x,y,m_hIcon); } else { CDialogEx::OnPaint(); }}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSORC服务器Dlg::OnQueryDragIcon(){ returnstatic_cast<HCURSOR>(m_hIcon);}//服务器线程UINTthread(LPVOIDp){ charbuff[100];//定义长度为100的字符数组用来容纳输入框输入的内容 CSizesize; size.cx=0; size.cy=30;//初始化信息显示框的输出位置 ints=1,msgcount,loop=1,flag=0; C服务器Dlg*dlg=(C服务器Dlg*)AfxGetApp()->GetMainWnd(); msgcount=dlg->getcount();//获得客户端数量 if(msgcount==-1) loop=0; if(loop) { s=1; dlg->msgsock[msgcount]=accept(dlg->sock,(sockaddr*)&(dlg->serv),&(dlg->addlen)); if(dlg->msgsock[msgcount]==INVALID_SOCKET) { dlg->m_edit1.SetWindowText("Erroraccept"); } else { AfxBeginThread(thread,0);//启动线程 dlg->SetForegroundWindow();//激活信息窗口 dlg->m_list.InsertItem(dlg->count++,"连接成功"); dlg->m_list.InsertItem(dlg->count++,inet_ntoa(dlg->serv.sin_addr));//连接成功之后在信息框显示客户端的IP dlg->m_list.Scroll(size); dlg->m_button.EnableWindow(TRUE);//允许输入框操作 while(s!=SOCKET_ERROR) { //循环接收数据 s=recv(dlg->msgsock[msgcount],buff,100,0); dlg->SetForegroundWindow(); if(s!=SOCKET_ERROR) { dlg->m_list.InsertItem(dlg->count++,buff);//换行后插入新信息 dlg->m_list.Scroll(size); dlg->sendtoall(dlg->msgsock[msgcount],buff); } } send(dlg->msgsock[msgcount],"Disconnected",100,0); dlg->m_list.InsertItem(dlg->count++,"Disconnected"); dlg->m_list.Scroll(size); dlg->msgsock[msgcount]=NULL; for(inti=0;i<50;i++) if(dlg->msgsock[i]!=NULL) flag=1; if(flag!=1) dlg->m_button.EnableWindow(FALSE); closesocket(dlg->msgsock[msgcount]); } } //终止线程 AfxEndThread(0); return0;}//发送数据voidC服务器Dlg::OnBnClickedButton1(){ //TODO:在此添加控件通知处理程序代码 /////////gettime/////////////////////////////////CTimet=CTime::GetCurrentTime();//获取当前电脑时间CStringstr; str.Format("(%d-%d-%d",t.GetYear(),t.GetMonth(),t.GetDay());//时间格式str+=t.Format("%H:%M:%S)"); char*time1; time1=(LPSTR)(LPCTSTR)str;//将时间转换为字符型 charallsend[200]; charinmessage[100]; m_edit2.GetWindowText(allsend,200);//读取用户名 strcat(allsend,":"); m_edit1.GetWindowText(inmessage,100);//读取输入框内容 strcat(allsend,inmessage); strcat(allsend,time1); m_edit1.SetWindowText(""); m_list.InsertItem(count++,allsend);//新一行显示的位置 CSizesize; size.cx=0; size.cy=30; m_list.Scroll(size); if(*inmessage==NULL)//不允许发送空消息 { AfxMessageBox("发送消息不可以为空"); return; }else { //循环向所有客户发送信息 for(inti=0;i<50;i++) { if(msgsock[i]!=NULL) { send(msgsock[i],allsend,100,0); } } }}C服务器Dlg::~C服务器Dlg(){ for(inti
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《安全感悟分享》课件
- 《职业适应与发展》课件
- 《生产安全事故应急》课件
- 2024教师发言稿(34篇)
- 艺术与人生和社会的关系
- 单位管理制度汇编大全【人事管理】
- 单位管理制度分享合集【人员管理篇】十篇
- 单位管理制度分享大合集【人员管理】十篇
- 单位管理制度范文大合集【员工管理篇】十篇
- 单位管理制度呈现大全【人员管理】
- TSG-T7001-2023电梯监督检验和定期检验规则宣贯解读
- 河南省平顶山市鲁山县2023-2024学年二年级上学期期末语文试卷
- 中原文化(历史篇)智慧树知到期末考试答案2024年
- 金蝶软件旗舰版月底结账作业流程操作
- (正式版)JBT 14762-2024 电动摩托车和电动轻便摩托车用阀控式铅酸蓄电池
- 劳动教育智慧树知到期末考试答案2024年
- 大疆慧飞无人机考试题库附有答案
- 初中历史统编九年级材料论述题观点整合(世界史)【学案】
- 2023-2024学年宜宾市数学九年级上册期末考试试题(含解析)
- 热电厂检修方案
- 2024年江苏省高中学业水平考试合格考生物试卷试题(含答案详解)
评论
0/150
提交评论