基于C/S 结构的IM即时通讯软件--上篇
目的:实现类似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即时通讯软件--上篇的更多相关文章
- 基于C/S 结构的IM即时通讯软件--下篇
3.实现界面事件函数 客户端:单击" 进入" 按钮发送请求,如果要与服务器通信,必须要同时发送结构体信息描述发送内容,便于服务器处理. void CCase010Dlg::OnBn ...
- 基于存储过程的MVC开源分页控件--LYB.NET.SPPager
摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件MVCPager(http://www.webdiyer.com/)算 ...
- 基于存储过程的MVC开源分页控件
基于存储过程的MVC开源分页控件--LYB.NET.SPPager 摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件M ...
- Web应用程序开发,基于Ajax技术的JavaScript树形控件
感谢http://www.cnblogs.com/dgrew/p/3181769.html#undefined 在Web应用程序开发领域,基于Ajax技术的JavaScript树形控件已经被广泛使用, ...
- FineUI 基于 ExtJS 的专业 ASP.NET 控件库
FineUI 基于 ExtJS 的专业 ASP.NET 控件库 http://www.fineui.com/
- 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>
上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...
- 为什么要用hibernate 与基于数据库表结构的项目开发
最近开始学习hibernate,其实并不知道要学习什么,有什么用.后来问了一下同事,他就说快捷方便简单,很多事情不用自己做他会帮你做好,但是我觉得不应该是这样的,于是我就去搜了一下,就搜到了一篇帖子, ...
- 基于Qt的第三方库和控件
====================== 基于Qt的第三方库和控件 ====================== libQxt -------- http://dev.libqxt.o ...
- java开源即时通讯软件服务端openfire源码构建
java开源即时通讯软件服务端openfire源码构建 本文使用最新的openfire主干代码为例,讲解了如何搭建一个openfire开源开发环境,正在实现自己写java聊天软件: 编译环境搭建 调试 ...
随机推荐
- Tempset 暴风射击
发售年份 1980 平台 街机 开发商 雅达利(Atari) 类型 射击 https://www.youtube.com/watch?v=AMto2HJJSSA
- C 语言经典例子
1. 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. #inc ...
- Flink
1. Flink表接受是基于dataset.datastream的:首先需要注册一个dataset,然后通过sql去查询这个dataset,返回的即使基于dataset查询结果,这个查询结构就是Fli ...
- 嵌入式C语言常见的错误
预处理的错误: #include “stdio.h” //引用符号错误 #inlcude <name> //自定义文件用 " " not find gcc -I ...
- C# partial 关健字说明
参考:http://blog.csdn.net/niemeiquan/article/details/7801803 1. 什么是局部类型? C# 2.0 引入了局部类型的概念.局部类型允许我们将一个 ...
- PowerShell ISE:Windows Server 2008 R2默认不安装
PowerShell ISE:Windows Server 2008 R2默认不安装,需要手动安装,在PowerShell运行如下两段脚本: Import-Module ServerManager A ...
- 【java】package
总结: 包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰. 不同包中的子类还可以直接访问父类中被protected权限修饰的成员. 包与包之间可以使用的权限只有两种,publi ...
- ThinkPHP3.2 中空方法、空控制器和空模块的设置
ThinkPHP3.2 中空方法.空控制器和空模块的设置 1.空方法设置 问题: 当你访问一个不存在的方法的时候: 如: http://localhost/test/index.php/Home/Us ...
- python基础知识15---三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数
阅读目录 一 三元表达式.列表推导式.生成器表达式 二 递归与二分法 三 匿名函数 四 内置函数 五 阶段性练习 一. 三元表达式.列表推导式.生成器表达式 1 三元表达式 name=input('姓 ...
- C# 6.0:String Interpolation
在开发中经常需要对字符串进行格式化处理.我们一般使用String.Format()方法,它会将指定字符串中的每个格式项替换为相应对象的值的文本等效项.虽然这很普通,但有时会容易使人迷惑并造成错误.因为 ...