基于 MFC 和 Socket 的聊天系统设计报告
大连理工大学
Dalian University of Technology
问题分析
聊天系统,利用 socket 通信机制实现简单的聊天室功能并完成客户端与服务器端 mfc
界面的绘制。
实现的功能有
* 账号登录和注册
* 服务器可以拒绝用户连接
* 用户之间互相发送在线消息
* 用户之间发送离线消息
* 在服务器端可以将客户登陆、退出及在线时间等情况记录并保存。
*服务器和客户端都可以将聊天记录保存。
*可以在客户端和服务器端传送文件
算法选择
1.基于 Socket 的套接字通讯
基于 Socket 的套接字编程实例
图 1 Socket 通信原理
2.Md5 加密
md5 的全称是 message-digest algorithm 5(信息-摘要算法),在 90 年代初由
mit laboratory for computer science 和 rsa data security inc 的 ronald l. rivest 开发出
来,经 md2、md3 和 md4 发展而来。
它的作用是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种
保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。使用该加
密方式可以有效验证文件完整性,防止文件被篡改。
方案设计
开发环境
操作系统
Windows 11 x64
SDK
10.0.17763.0
在静态库中使用
MFC
在静态库中使用 MFC
集成开发环境
Visual Studio 2017 (v141)
消息传输格式设计
消息格式要保证知道消息是谁发出的,发给谁,应该怎末处理这段消息。谁发出的,发
给谁,设置了消息来源,去向等字段。为了解决怎末处理这段消息的问题,设置了消息类型
字段。
消息类型有 TYPE_ChatMsg , TYPE_Server_is_closed , TYPE_UserList , TYPE_OnlineState ,
TYPE_FileSend , TYPE_FileData , TYPE_AskFileData , TYPE_File_NO , TYPE_File_Over ,
TYPE_File_Fail , TYPE_LoginFail , TYPE_UserIsOnline , TYPE_OfflineMsg , TYPE_AllUser ,
TYPE_AddUserList , TYPE_I_am_online , TYPE_Logout , TYPE_Login , TYPE_Register , TYPE_Status
等用于登录,下线,注册,消息,文件的私发,群发,服务器是否故障等情况分别使用。
struct MyMsg
{
CString userId; //用户名
CString pw; //密码
CString type; //消息类型
CString fromUser; //消息来自
CString toUser; //消息去向
CString data; //消息内容
explicit MyMsg(CString str = "");
//载入消息,即解析消息。OLMsg 标记是否是离线消息
CString load(CString str, bool OLMsg = 0);
//连接消息各个部分,即封装消息
CString join(CString _data = "", CString _type = "", CString _user = "",
CString _from = "", CString _to = "", CString _pw = "") const;
//返回去除 str 前 n 个字符之后的右边剩余的子串
static CString rightN(const CString &str, int n) {
return str.GetLength() > n ? str.Right(str.GetLength() - n) : "";
}
};
服务器设计
基本流程
图 2
服务器端计划实现的功能
开放关闭端口
需要利用互斥锁机制保证最多只有一个服务器程序正在运行
对已经注册的用户信息进行保存
对用户注册请求进行确认
对用户登入请求进行确认
需要暂存接收对离线用户的消息,文件等
检查某个用户是否在线
验证用户名和密码是否有效
利用消息进行文件传输,并对文件进行 md5 运算来验证文件完整性
类的设计
class CmfcServer1Dlg : public CDialogEx
{
#define DATASRC CString("UserData.dat")
#define OLMSG CString("offlineMsg")
public:
CmfcServer1Dlg(CWnd* pParent = NULL); // 标准构造函数
~CmfcServer1Dlg();
// 对话框数据
enum { IDD = IDD_MFCSERVER1_DIALOG };
protected:
HICON m_hIcon;
virtual BOOL OnInitDialog();
virtual void OnOK();
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
private:
const static int UserNumMax = 100; //允许登录的用户最大数量
struct _UserInfo {
char userName[17]; //用户名
char pwd[17]; //密码
bool isOnline; //在线状态
bool isRefused; //是否被拒绝登录
} userInfo[UserNumMax];
typedef std::map<std::string, CServerSocket*> UserSocket;
UserSocket user_socket; //保存<用户名,socket>映射关系
int userNum; //所有已注册用户数
CString userList; //用户列表,在用户登录时将发给用户