C++ 课程设计-聊天系统.doc_第1页
C++ 课程设计-聊天系统.doc_第2页
C++ 课程设计-聊天系统.doc_第3页
C++ 课程设计-聊天系统.doc_第4页
C++ 课程设计-聊天系统.doc_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

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

文档简介

c+聊天系统一、该聊天系统需要实现的功能:1、用户之间能够进行私聊。2、输出聊天信息。3、显示聊天信息。4、自动显示所有在线成员。二、开发环境操作系统:windows xp2000ide:vc 6.0语言:c+框架:mfc三、结构为了保证聊天信息的实时性和系统的效率,聊天室系统使用c/s结构,由服务器端程序和客户端程序两部分组成。服务器端和客户端通过tcp协议进行通信。其中,客户端用于显示来自服务器端的聊天信息,接收用户的输入信息并发送给服务器端,服务器端用于接受来自客户端的信息,处理之后转发给聊天室中的其他用户。tcp:transmission control protocol 传输控制协议tcp是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(transport layer)通信协议,由ietf的rfc 793说明(specified)。在简化的计算机网络osi模型中,它完成第四层传输层所指定的功能,udp是同一层内另一个重要的传输协议。在因特网协议族(internet protocol suite)中,tcp层是位于ip层之上,应用层之下的运输层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是ip层不提供这样的流机制,而是提供不可靠的包交换。四、基本流程启动服务器,服务器开始监听。客户端向服务端发送连接请求,如果该客户已经登陆,则服务器向客户端反馈登录失败信息,如果登录成功,服务器将客户的登录信息记入服务器日志中。登陆成功后,用户界面的用户列表里将显示其他已经登录的用户,用户可以双击其他用户名,向他发送信息。发送的信息经过服务器发送至目的用户。当用户登出时,服务器将其用户名发送给其他用户,其他客户端将其从用户列表中删除五、部分主要程序代码客户端头文件 clientdlg.hclass cclientdlg : public cdialog/ constructionpublic:cclientdlg(cwnd* pparent = null);/ standard constructor/ dialog data/afx_data(cclientdlg)enum idd = idd_client_dialog ;clistboxm_lituser;ceditm_eduid;ceditm_edsend;ceditm_edrever;ceditm_edrev;cbuttonm_btstop;cbuttonm_btstart;cbuttonm_btsend;/afx_data/ classwizard generated virtual function overrides/afx_virtual(cclientdlg)protected:virtual void dodataexchange(cdataexchange* pdx);/ ddx/ddv support/afx_virtual/ implementationprotected:cclientsocketm_sktclient;boolm_bisloginok;cstringm_struid; protected:void disposeloginout(net_pack *path);void disposeuserin(net_pack *pack);void disposetransmiterr(net_pack *path);void disposetransmit(net_pack *path);void disposeloginstopsvr(net_pack *path);void disposeloginerr(net_pack *path);void btsend();void disposeloginok(net_pack* path);void userlogout();bool userlogin();hicon m_hicon;/ generated message map functions/afx_msg(cclientdlg)virtual bool oninitdialog();afx_msg void onsyscommand(uint nid, lparam lparam);afx_msg void onpaint();afx_msg hcursor onquerydragicon();afx_msg void onbuttonstart();afx_msg void onchangeedituid();afx_msg void onbuttonstop();afx_msg lresult onnetreceive(wparam wparam, lparam lparam);afx_msg void onbuttonsend();afx_msg void onclose();afx_msg void onselchangelistuser();/afx_msgdeclare_message_map();客户端源文件部分代码void cclientdlg:onbuttonstop() / todo: add your control notification handler code hereuserlogout();bool cclientdlg:userlogin()/登陆 m_eduid.getwindowtext(m_struid); if(m_struid.isempty() :afxmessagebox(_t(uid cant be null !); return false; if(!m_sktclient.create() :afxmessagebox(_t(do not creat!); return false; if(!m_sktclient.connect(_t(127.0.0.1),5555) :afxmessagebox(_t(connect error!); net_pack path;memset(&path,0,sizeof(path);path.fun=login; lstrcpy(path.senderid,m_struid.getbuffer(m_struid.getlength();m_struid.releasebuffer(); m_sktclient.send(&path,sizeof(net_pack); / m_lituser.addstring() return true;void cclientdlg:userlogout()net_pack pack;memset(&pack,0,sizeof(net_pack);pack.fun=logout;lstrcpy(pack.senderid,m_struid.getbuffer(m_struid.getlength();m_sktclient.send(&pack,sizeof(net_pack);m_sktclient.close();m_struid=_t();m_eduid.setwindowtext(m_struid); m_eduid.enablewindow(true);m_btstart.enablewindow(true);m_btsend.enablewindow(false);m_edsend.enablewindow(false);m_edrever.enablewindow(false);m_btstop.enablewindow(false);lresult cclientdlg:onnetreceive(wparam wparam, lparam lparam) lresult ret=0; net_pack *path=(net_pack *)wparam;switch(path-fun)case loginok:disposeloginok(path);break; case loginerr:disposeloginerr(path);break; case stopserver:disposeloginstopsvr(path);break; case transmit:disposetransmit(path);break; case transmiterr:disposetransmiterr(path);break; case userin:disposeuserin(path); break; case userout:disposeloginout(path);break;delete path;return ret;void cclientdlg:disposeloginok(net_pack *path) m_bisloginok=true; m_eduid.enablewindow(false);m_btstart.enablewindow(false);m_btsend.enablewindow(true);m_edsend.enablewindow(true);m_edrever.enablewindow(true);m_btstop.enablewindow(true);void cclientdlg:btsend()/发送信息 cstring strsend,strrcverid;/发送的内容以及接收对象 m_edsend.getwindowtext(strsend); m_edrever.getwindowtext(strrcverid); if(strsend.isempty()|strrcverid.isempty() return; net_pack pack; memset(&pack,0,sizeof(net_pack); pack.fun=transmit; lstrcpy(pack.reverid,strrcverid.getbuffer(strrcverid.getlength(); lstrcpy(pack.senderid,m_struid.getbuffer(m_struid.getlength(); lstrcpy(pack.content,strsend.getbuffer(strsend.getlength(); m_sktclient.send(&pack,sizeof(net_pack); strsend=(_t(); m_edsend.setwindowtext(strsend);void cclientdlg:disposeloginerr(net_pack *path):afxmessagebox(登录失败!); m_struid=_t();m_eduid.setwindowtext(m_struid);void cclientdlg:disposeloginstopsvr(net_pack *path)cstring str;str = _t(停机检修!); :afxmessagebox(str);void cclientdlg:disposetransmit(net_pack *path) cstring strcontent; ctime tm = ctime:getcurrenttime(); cstring strtime = tm.format(_t(%y/%m/%d %h:%m:%s); strcontent.format(%s %srn%srn, path-senderid, strtime, path-content); m_edrev.setsel(m_edrev.getwindowtextlength(), m_edrever.getwindowtextlength(); m_edrev.replacesel(strcontent);void cclientdlg:disposetransmiterr(net_pack *path) cstring str; str=_t(查无此货!); :afxmessagebox(str);void cclientdlg:onbuttonsend() / todo: add your control notification handler code herebtsend();void cclientdlg:onclose() / todo: add your message handler code here and/or call defaultuserlogout();cdialog:onclose();void cclientdlg:onselchangelistuser() / todo: add your control notification handler code here cstring str; int index = m_lituser.getcaretindex();/获取所选数字在listbox中的位置 m_lituser.gettext(index,str);/将所对应数字赋给str m_edrever.setwindowtext(str);/将其显示到m_edrever上 void cclientdlg:disposeuserin(net_pack *pack)cstring struid;struid = pack-senderid;if(struid != m_struid)m_lituser.addstring(pack-senderid);/登陆成功,将其加入listbox中 void cclientdlg:disposeloginout(net_pack *path) if(path-fun = userout) int index = m_lituser.findstring(0,path-senderid);/登录失败 m_lituser.deletestring(index);服务器头文件dlg_sevrdlg.hclass cmydlg : public cdialog/ constructionpublic:cmydlg(cwnd* pparent = null);/ standard constructor/ dialog data/afx_data(cmydlg)enum idd = idd_my_dialog ;clistctrlm_lctest;cbuttonm_btstop;cbuttonm_btstart;/afx_data/ classwizard generated virtual function overrides/afx_virtual(cmydlg)protected:virtual void dodataexchange(cdataexchange* pdx);/ ddx/ddv support/afx_virtual/ implementationprotected:clistensocket m_socklisten;protected:void listinfor(net_pack *ppack,cclientsocket *socket);void dellist(cstring struid);void listadd(cstring struid,cstring strevent);void initcontrol();void disposelogout(net_pack *ppack, cclientsocket *psocket);void disposetransmit(net_pack *ppack, cclientsocket *psocket);cclientsocket * findsocketbyid(cstring struid);void disposelogin(net_pack *ppack, cclientsocket *psocket);void ctrl();void serstop();void serstart();hicon m_hicon;/ generated message map functions/afx_msg(cmydlg)virtual bool oninitdialog();afx_msg void onsyscommand(uint nid, lparam lparam);afx_msg void onpaint();afx_msg hcursor onquerydragicon();afx_msg void onbuttonstart();afx_msg void onbuttonstop();afx_msg lresult onnetreceive(wparam wparam, lparam lparam);afx_msg void onclose();/afx_msgdeclare_message_map();服务器源文件部分代码void cmydlg:onbuttonstop() / todo: add your control notification handler code hereserstop();void cmydlg:serstart() if(!m_socklisten.create(5555) :afxmessagebox(_t(创建失败!); return; if(!m_socklisten.listen() :afxmessagebox(_t(监听失败!); m_socklisten.close(); return; m_btstart.enablewindow(false); m_btstop.enablewindow(true); listadd(_t(服务器),_t(服务器开启);void cmydlg:serstop()if(m_socklisten.m_hsocket != null) m_socklisten.close(); cclientsocket *pstkclt=null; net_pack pack;memset(&pack, 0, sizeof(net_pack);pack.fun = stopserver;/lstrcpy(pack.content,_t(停机检修!);map:iterator it;for(it = cclientsocket:m_mapuidskt.begin(); it != cclientsocket:m_mapuidskt.end();it+) pstkclt = it-second; pstkclt-send(&pack,sizeof(net_pack); pstkclt-close(); delete pstkclt; m_btstart.enablewindow(true); m_btstop.enablewindow(false); /m_lctest.getitemtext(); /listadd(_t(服务器),_t(服务器退出); dellist(_t(服务器);void cmydlg:ctrl() m_btstart.enablewindow(true); m_btstop.enablewindow(false);lresult cmydlg:onnetreceive(wparam wparam, lparam lparam) lresult ret=0; net_pack *path=(net_pack *)wparam; cclientsocket *sktclt=(cclientsocket *)lparam; switch(path-fun) case login: disposelogin(path,sktclt); break; case logout: disposelogout(path,sktclt); break; case transmit: disposetransmit(path,sktclt); break; delete path; return 0;void cmydlg:disposelogin(net_pack *ppack, cclientsocket *psocket)/登陆函数作用:判断uid在map中是否已有,如有 cclientsocket *psktclt = findsocketbyid(ppack-senderid);cstring struid = ppack-senderid;/struid.format(%d,ppack-senderid);net_pack pack;memset(&pack, 0, sizeof(net_pack);if(psktclt=null) pack.fun=loginok; /lstrcpy(pack.senderid,struid.getbuffer(struid.getlength(); psocket-send(&pack,sizeof(net_pack); cclientsocket:m_mapuidsktppack-senderid = psocket; /cstring strcontent; /ctime tm = ctime:getcurrenttime(); /cstring strtime = tm.format(_t(%y/%m/%d %h:%m:%s); /static int i=0 /m_lctest.insertitem(0,_t(i+),0); listadd(struid,_t(客户端登录); /pack.fun=userin;/lstrcpy(pack.senderid,struid.getbuffer(struid.getlength();/可以将一个字符数组付给字符串,但是相反则不能,前者有运算符重载 /pack.senderid = struid; /map:iterator itr; /psocket-send(&pack,sizeof(net_pack); ppack-fun = userin; listinfor(ppack,psocket);else pack.fun=loginerr; psocket-send(&pack,sizeof(net_pack); psocket-close(); delete psocket;cclientsocket * cmydlg:findsocketbyid(cstring struid)/map:iterator ite; /ite = cclientsocket:m_mapuidsktmap:iterator itr;itr = cclientsocket:m_mapuidskt.find(struid);/函数返回值是个迭代器if(itr!=cclientsocket:m_mapuidskt.end()return cclientsocket:m_mapuidsktstruid;elsereturn null;/return void cmydlg:disposetransmit(net_pack *ppack, cclientsocket *psocket) cclientsocket *sktrece = findsocketbyid(ppack-reverid);if(sktrece != null) /net_pack pack; 原样输出到指定客户端界面 /memset(&pack,0,sizeof(net_pack); /pack.fun=transmit; /:lstrcpy(pack.content)sktrece-send(ppack,sizeof(net_pack);elsenet_pack pack;memset(&pack,0,sizeof(net_pack);pack.fun=transmiterr;/lstrcpy(pack.content,_t(查无此货!); sktrece-send(ppack,sizeof(net_pack);void cmydlg:disposelogout(net_pack *ppack, cclientsocket *psocket) cstring struid; struid = ppack-senderid; cclientsocket *socket = cclientsocket:m_mapuidsktppack-senderid; ppack-fun = userout; listinfor(ppack,psocket); socket-close(); delete socket; cclientsocket:m_mapuidskt.erase(ppack-senderid); /listadd(struid,_t(客户端退出); dellist(struid); void cmydlg:onclose() / todo: add your message handler code here and/or call defaultserstop();cdialog:onclose();void cmydlg:initcontrol()/ /显示模式设置 m_lctest.setextendedstyle(lvs_ex_gridlines);/一列形式显示出来 m_lctest.insertcolumn(0,_t(序号),lvcfmt_center,110); m_lctest.insertcolumn(1,_t(用户名),lvcfmt_center,110); m_lctest.insertcolumn(2,_t(时间),lvcfmt_center,110); m_lctest.insertcolumn(3,_t(事件),lvcfmt_center,130); m_lctest.setbkcolor(rgb(0,255,0); /m_lctest.insertcolumn(1,_t(用户名),lvcfmt_center,110); /* m_lctest.insertcolumn(0,_t(序号),lvcfmt_center,110);/插入列 m_lctest.insertcolumn(1,_t(用户名),lvcfmt_center,110); m_lctest.insertcolumn(2,_t(时间),lvcfmt_center,110); m_lctest.insertcolumn(3,_t(事件),lvcfmt_center,125); m_lctest.setbkcolor(rgb(0,255,0);*/void cmydlg:listadd(cstring struid,cstring strevent) int count = m_lctest.getitemcount();/获取当前行数,从零开始 获取列表视图控件项的数目cstring scount; scount.format(%d,count+1);/将其转化成字符串,从一开始ctime ct = ctime:getcurrenttime();/获取当前时间cstring stime

温馨提示

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

评论

0/150

提交评论