目的:实现类似QQ群聊的聊天室,可以看到好友列表及互相传送信息。

分析:可基于C/S结构实现即时通讯

1、创建基于对话框的MFC程序(支持windows套接字),并增加相应的类与结构体,完善对话框界面。

服务器端:新增两个基于CSocket的类CClientSocket/CServerSocket分别用于服务与监听;并新增一个结构体信息,用于对客户端传输的信息(消息类型与长度)进行甄别。

    

客户端:新增基于CSocket的类CClientSocket用于服务;并新增一个结构体信息,用于对客户端传输的信息(消息类型与长度)进行甄别。

结构体信息,用于标识传输的内容类型

  1. typedef struct tagHeader
  2. {
  3. char type;
  4. int len;
  5. }Header, *pHeader;
  6. #define LOGIN_IO 1 //后面可以继续完善,比如视频/音频/文件
  7. #define SEND_MESSAGE 3
  8. ;

2、完善框架结构

服务器:在Clientsocket.h声明Dlg类,便于进行指针操作,并标识登录的用户昵称,创建CPtrList链队列数据结构。

  1. class CCase006Dlg;
  2. class CClientSocket : public CSocket
  3. {
  4. public:
  5. CString m_strName; //请求登录的用户
  6. CPtrList *clist; //储存队列的结构
  7. CCase006Dlg* m_dlgserver; //对话框指针机制
  8. CClientSocket(CPtrList*list); //生成一个socket队列
  9.  
  10. CCase006Dlg* m_Dlg;
  11. void GetDlg(CCase011Dlg *dlg);
    12 }

在Clientsocket.cpp中包含结构体头文件,并实现指针函数

  1. #include "tagHeader.h"
  2.  
  3. // CClientSocket
  4. CClientSocket::CClientSocket(CPtrList *list) : m_dlgserver(NULL)
  5. {
  6. clist=list;
  7. }

在CSeverSocket.h中定义列表对象-CPtrList connectList;

在CSeverSocket.cpp中添加结构体头文件;

在CXXXXDlg.h中声明套接字类,并定义指针对象与用户列表更新函数

  1. 1 class CServerSocket; //监听套接字类
  2. 2 class CClientSocket; //创建与客户端通信的套接字类
  3. 3
    // CCase006Dlg 对话框
  4. 4 class CCase006Dlg : public CDialog
  5. 5 {
  6. 6 // 构造
  7. 7 public:
  8. 8 CCase006Dlg(CWnd* pParent = NULL); // 标准构造函数
  9. 9 CString m_str_name; //用于标识管理员名
  10. 10 CClientSocket* clientsocket; //定义套接字指针
  11. 11 CServerSocket* m_serversocket;
  12. 12 void UpdateUser(CClientSocket* psocket); //声明用户更新函数

在CXXXXDlg.cpp中包含头文件,并在初始化函数中初始化Socket指针对象

  1. #include "ServerSocket.h"
  2. #include "ClientSocket.h"
  3. #include "tagHeader.h"
  4.  
  5. BOOL CCase006Dlg::OnInitDialog()
  6. {
  7. serversocket=NULL;
  8. clientsocket =NULL;
  9. ......
  10. }

客户端:在 Clientsocket.h中定义登录用户名,并定义一个窗口指针及函数

  1. 1 class CCase005Dlg; //注意声明类
  2. 2 class CClientSocket : public CSocket
  3. 3 {
  4. 4 public:
  5. 5 CCase005Dlg *m_Dlg;
  6. 6 CString m_str_name; //登录用户
  7. 7 void GetDlg(CCase005Dlg *dlg);
  8. 8 };

在ClientSocket.cpp中声明结构体,并实现窗口指针获取函数

  1. #include "Case005Dlg.h"
  2. #include "tagHeader.h"
  3.  
  4. // CClientSocket 成员函数
  5. void CClientSocket::GetDlg(CCase005Dlg *dlg)
  6. {
  7. m_dlg=dlg;
  8. }

在CXXXXDlg.h中声明套接字类,并定义指针对象与用户列表更新函数以及是否获取信息函数

  1. #include "ClientSocket.h"
  2.  
  3. class CCase005Dlg : public CDialog
  4. {
  5. // 构造
  6. public:
  7. CClientSocket *m_clientsocket;
  8. void Updateuser();
  9. BOOL GetmsgFromRoom();
  10. ......
  11. }

在CXXXXDlg.cpp中包含头文件,并在初始化函数中初始化Socket指针对象

  1. #include "ClientSocket.h"
  2. #include "tagHeader.h"

此时已完成基本框架体系结构,接下来实现通信相关函数。

3、实现界面事件函数

服务器端:单击" 开始" 按钮开始监听

  1. 1 void CCase011Dlg::OnBnClickedBnOpen()
  2. 2 {
  3. 3 // TODO: 在此添加控件通知处理程序代码
  4. 4 UpdateData();
  5. 5 serversocket=new CServerSocket; //开启服务,定义一个服务对象
  6. 6
  7. 7 BYTE nfield[4];
  8. 8 CString strIP;
  9. 9 UpdateData(); //需要更新
  10. 10
  11. 11 //将IP传给地址框
  12. 12 m_edit_ip.GetAddress(nfield[0],nfield[1],nfield[2],nfield[3]);
  13. 13 strIP.Format("%d.%d.%d.%d",nfield[0],nfield[1],nfield[2],nfield[3]);
  14. 14 CTime time=CTime::GetCurrentTime();
  15. 15
  16. 16 if(m_str_name.IsEmpty()) //对输入信息判定,,可简写
  17. 17 {
  18. 18 AfxMessageBox("请先登记管理员名!");
  19. 19 return ;
  20. 20 }
  21. 21 if(m_edit_ip.IsBlank())
  22. 22 {
  23. 23 AfxMessageBox("请配置聊天室IP");
  24. 24 return ;
  25. 25 }
  26. 26 if(m_str_port.IsEmpty())
  27. 27 {
  28. 28 AfxMessageBox("请配置要开放的端口");
  29. 29 return ;
  30. 30 }
  31. 31
  32. 32 //开启聊天室,首先创建用于监听的套接字
  33. 33 if(serversocket->Create(atoi(m_int_port),1,strIP))
  34. 34 {
  35. 35 m_editbox.SetWindowText("");
  36. 36 m_editbox.ReplaceSel("聊天室开启成功!\r\n"); //此处使用的是编辑框控件,所以需使用replaceSel
    CString temp=time.Format("%Y-%m-%d"); //增加时间排头
  37. 37 m_editbox.ReplaceSel("日期:"+temp+"\r\n"); //编辑框输出信息
  38. 38 temp=time.Format("%H:%M:%S");
  39. 39 theApp.m_str_name=m_str_name; //如果想要实现聊天界面标题为登录者
  40. 40 m_editbox.ReplaceSel(temp+" 管理员"+theApp.m_str_name+"开放聊天室\r\n");
  41. 41 }
  42. 42 if(serversocket->Listen()) //打开监听
  43. 43 {
  44. 44 m_editbox.ReplaceSel("等待成员加入。。。\r\n");
  45. 45 }
  46. 46 //目前无人,因此仅有管理员一人在线
  47. 47 m_listbox.ResetContent();
  48. 48 m_listbox.AddString(theApp.m_str_name+"(管理员)");
  49. 49 this->SetWindowTextA("管理员:"+m_str_name+"服务器端");
  50. 50 }

更新用户列表处理函数

  1. void CCase011Dlg::UpdateUser(CClientSocket* psocket)
  2. {
  3. m_listbox.ResetContent(); //清空列表
  4. m_listbox.AddString(theApp.m_strName+"(管理员)"); //添加管理员用户
  5.  
  6. CString userInfo;
  7. userInfo = theApp.m_str_ame+"(管理员)"+"&"; //添加管理员信息
  8. if(clientsocket!=NULL)
  9. {
  10. CClientSocket* psock=NULL;
  11. POSITION pos=clientsocket->clist->GetHeadPosition(); //获取列表头位置
  12. while(pos!=NULL)
  13. {
  14. psock=(CClientSocket*)clientsocket->clist->GetNext(pos);
  15. m_listbox.AddString(psock->m_str_name);
  16. userInfo+=(psock->m_strName+"&"); //逐个增加已经记录的用户名
  17. }
  18. Header head;
  19. head.type=LOGIN_IO;
  20. head.len=userInfo.GetLength();
  21. POSITION po=clientsocket->clist->GetHeadPosition();
  22. while(po!=NULL) //将最新的用户列表转发给各个用户
  23. {
  24. psock=(CClientSocket*)clientsocket->clist->GetNext(po);
  25. psock->Send((char*)&head,sizeof(Header));
  26. psock->Send((LPCTSTR)userInfo,userInfo.GetLength());
  27. }
  28. }
  29. }

基于C/S 结构的IM即时通讯软件--上篇的更多相关文章

  1. 基于C/S 结构的IM即时通讯软件--下篇

    3.实现界面事件函数 客户端:单击" 进入" 按钮发送请求,如果要与服务器通信,必须要同时发送结构体信息描述发送内容,便于服务器处理. void CCase010Dlg::OnBn ...

  2. 基于存储过程的MVC开源分页控件--LYB.NET.SPPager

    摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件MVCPager(http://www.webdiyer.com/)算 ...

  3. 基于存储过程的MVC开源分页控件

    基于存储过程的MVC开源分页控件--LYB.NET.SPPager 摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件M ...

  4. Web应用程序开发,基于Ajax技术的JavaScript树形控件

    感谢http://www.cnblogs.com/dgrew/p/3181769.html#undefined 在Web应用程序开发领域,基于Ajax技术的JavaScript树形控件已经被广泛使用, ...

  5. FineUI 基于 ExtJS 的专业 ASP.NET 控件库

    FineUI 基于 ExtJS 的专业 ASP.NET 控件库 http://www.fineui.com/

  6. 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>

    上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...

  7. 为什么要用hibernate 与基于数据库表结构的项目开发

    最近开始学习hibernate,其实并不知道要学习什么,有什么用.后来问了一下同事,他就说快捷方便简单,很多事情不用自己做他会帮你做好,但是我觉得不应该是这样的,于是我就去搜了一下,就搜到了一篇帖子, ...

  8. 基于Qt的第三方库和控件

    ====================== 基于Qt的第三方库和控件 ======================     libQxt --------   http://dev.libqxt.o ...

  9. java开源即时通讯软件服务端openfire源码构建

    java开源即时通讯软件服务端openfire源码构建 本文使用最新的openfire主干代码为例,讲解了如何搭建一个openfire开源开发环境,正在实现自己写java聊天软件: 编译环境搭建 调试 ...

随机推荐

  1. C#知识点汇总

    核心技术课程 编程基础强化练习.面向过程编程(变量.if.for.while.函数.类型转换.枚举 .数组.重载.值类型.引用类型.ref.out.字符串).面向对象编程(类.继承 .接口.异常.索引 ...

  2. 我发起并创立了一个 Javascript 前端库 开源项目 jWebForm

    在线演示地址: ( 在线演示 云平台 由 Kooboo 提供  https://www.kooboo.com/ ) 按钮:      http://iwebform.kgeking.kooboo.si ...

  3. Kettle解决方案: 第五章 ETL相关知识

    早期, ETL知识作为BI系统的一部分来介绍. 后来在The Data Warehouse ETL Tooket一书中, 系统性的整理了ETL的相关内容, 形成了一篇"ETL里的34个子系统 ...

  4. Java中所涉及到的设计模式小记

    一.JAVA设计模式一共有23中.其中这23中大体可以分为3类,具体分法如下所示: 1.创建型模式:涉及到的设计模式共5种,分别是: 工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 2.结 ...

  5. 使用 GDB 调试需要命令行参数的程序

    使用 gdb 命令提供的 --args 选项可以调试需要命令行参数的程序,如下: gdb --args a.out arg1 arg2 arg3

  6. 使用powerpoint的表对象

    以下为basic范例,delphi使用需要加以修改 Table 对象 代表幻灯片上的表格形状.Table 对象是 Shapes 集合的成员.Table 对象包含 Columns 集合和 Rows 集合 ...

  7. 玩了下opencv的aruco(python版)

    简单的玩了下opencv里头的aruco,用的手机相机,手机装了个 ip摄像头,这样视频就可以传到电脑上了. 首先是标定,我没打印chessboard,直接在电脑屏幕上显示,拍了17张,大概如下: 又 ...

  8. windows环境下ElasticSearch6 安装head插件

    转: https://blog.csdn.net/shubingzhuoxue/article/details/80998738 https://blog.csdn.net/camelcanoe/ar ...

  9. [UE4]显示落地箭头

    一.Set Hidden in Game:隐藏对象 Propagate to Children:是否修改容器子对象的可见性. 二.添加2个Static Mesh,分别命名为:StaitcMeshArr ...

  10. java 调用c# web api 代码

    上次我们写的.net  web api 给对方公司的java团队调用,他们觉得说java无法调用.net 写的api ,靠居然有这事,索性自己写一个java的demo给他们 使用apache的Http ...