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

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

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

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

    

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

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

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

2、完善框架结构

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

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

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

 #include "tagHeader.h"

 // CClientSocket
CClientSocket::CClientSocket(CPtrList *list) : m_dlgserver(NULL)
{
clist=list;
}

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

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

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

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

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

 #include "ServerSocket.h"
#include "ClientSocket.h"
#include "tagHeader.h" BOOL CCase006Dlg::OnInitDialog()
{
serversocket=NULL;
clientsocket =NULL;
......
}

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

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

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

 #include "Case005Dlg.h"
#include "tagHeader.h" // CClientSocket 成员函数
void CClientSocket::GetDlg(CCase005Dlg *dlg)
{
m_dlg=dlg;
}

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

 #include "ClientSocket.h"

 class CCase005Dlg : public CDialog
{
// 构造
public:
CClientSocket *m_clientsocket;
void Updateuser();
BOOL GetmsgFromRoom();
......
}

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

 #include "ClientSocket.h"
#include "tagHeader.h"

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

3、实现界面事件函数

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

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

更新用户列表处理函数

void CCase011Dlg::UpdateUser(CClientSocket* psocket)
{
m_listbox.ResetContent(); //清空列表
m_listbox.AddString(theApp.m_strName+"(管理员)"); //添加管理员用户 CString userInfo;
userInfo = theApp.m_str_ame+"(管理员)"+"&"; //添加管理员信息
if(clientsocket!=NULL)
{
CClientSocket* psock=NULL;
POSITION pos=clientsocket->clist->GetHeadPosition(); //获取列表头位置
while(pos!=NULL)
{
psock=(CClientSocket*)clientsocket->clist->GetNext(pos);
m_listbox.AddString(psock->m_str_name);
userInfo+=(psock->m_strName+"&"); //逐个增加已经记录的用户名
}
Header head;
head.type=LOGIN_IO;
head.len=userInfo.GetLength();
POSITION po=clientsocket->clist->GetHeadPosition();
while(po!=NULL) //将最新的用户列表转发给各个用户
{
psock=(CClientSocket*)clientsocket->clist->GetNext(po);
psock->Send((char*)&head,sizeof(Header));
psock->Send((LPCTSTR)userInfo,userInfo.GetLength());
}
}
}

基于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. [R] [Johns Hopkins] R Programming 作業 Week 2 - Air Pollution

    Introduction For this first programming assignment you will write three functions that are meant to ...

  2. edgedb 内部pg 数据存储的探索 (四) 源码编译

      edgedb 基于python开发,同时源码重包含了好多子项目,以下进行简单的源码编译 clone 代码 需要递归处理,加上recursive,比较慢稍等 git clone --recursiv ...

  3. HBASE 基础命令总结

    HBASE基础命令总结 一,概述 本文中介绍了hbase的基础命令,作者既有记录总结hbase基础命令的目的还有本着分享的精神,和广大读者一起进步.本文的hbase版本是:HBase 1.2.0-cd ...

  4. Filebeat工作过程(二)

    Filebeat简介 Filebeat是一个轻量级的收集日志和传输日志的工具(一直以为Filebeat是存储数据,并不是的它只是做一个收集传输功能):Filebeat安装在每一个你想要收集日志的服务器 ...

  5. celery+Rabbit MQ实战记录

    基于以前的一篇文章,celery+Rabbit MQ的安装和使用, 本文更加详细的介绍如何安装和使用celey, Rabbit MQ. 并记录在使用celery时遇到的一些问题. 1.安装 Rabbi ...

  6. cut字符串截取

    cut字符串截取 -d 按字节截取 [root@slave elk]# ll total 0 drwxr-xr-x. 6 root root 194 Jan 24 16:15 bigdesk 截取前2 ...

  7. 通用唯一识别码UUID

    UUID 概念:UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,目前最广泛应用的UUID,是微软公司的全局唯一标识符(GUID),而其他重要的应用,则 ...

  8. Vbox隐藏虚拟机,实现后台运行

    Vbox隐藏虚拟机,实现后台运行   1.进入vBox安装位置的命令行 D:\Program Files\VirtualBox> 2.执行命令: .\VBoxManage startvm Xp_ ...

  9. Spring boot 线上部署

    1.修改Spring Boot 1.添加:spring-boot-maven-plugin 插件 <build> <plugins> <plugin> <gr ...

  10. Quartz公共类,log4net 日志分目录 ,调度任务。

    版本:Quartz 2.5 ,log4net 2.0.8 QuartzHelper namespace Job.Common { public class QuartzHelper { private ...