17.MFC开发多人聊天室

1.本章说明

前面一章我们已经学会了如何用C/C++语言进行网络编程,但那却仅限于最简单的一对一聊天,和我们平时用的QQ、微信的功能也差太多了。

所以本章将结合前面学到的MFC界面编程的知识,带领大家开发一个聊天软件,它的主要功能就是群聊。

本文项目源码的链接放在了文章末,需要的可以自取,如果觉得困难的,可以直接参照源码对照本文学习即可。

如果需要添加更多强大的功能,比如单聊、文件传输等等,可以参考另外两篇文章:

  1. 手写一个聊天室(单聊、群聊、文件传输)
  2. Qt实现多人聊天室(单聊、群聊、文件传输)

2.聊天室服务器

2.1 建立项目

聊天最重要的是什么?那当然是信息正确性,即对方是否收到了正确的信息,为了这个目的,那当然就是选择TCP协议了,因为它的特点之一就是可靠性!

而UDP协议主要运用于视频传输中,比如打微信视频,网不好的时候就会出现卡顿、丢帧,但这也并不是太影响整体的交流过程。

其次就是服务器形式,服务器仅仅只是用于转发信息而已,那自然是用不着图形化界面的,建立一个控制台项目即可。

过程相信大家都会了,那我也就不再演示如何建立一个项目了,我这里新建的一个解决方案名字为LANChat,然后服务器项目的名称为LANServer,客户端的先不用管,后面我再进行讲解:

image-20231214142519264

然后服务器里面只有两个文件,首先是server.cpp文件,这是这个服务器主要且唯一的源文件,main函数入口在里面。

然后还有一个头文件名字为CNetServer.h,这个用于我们封装类,便于使用,下面就要开始进行讲解。

2.2 封装套接字

上一章使用了TCP来进行服务器与客户端进行聊天的时候,我们发现很多步骤其实都是固定的,但每次却又不得不写,会相当的麻烦,比如初始化网络环境这一步骤。

所以为了更加有效率的开发软件,以及理解类的作用,首先我们要开始进行封装。

考虑到服务器端是需要两种套接字的:

  1. 监听套接字:等待客户端的连接。
  2. 收发数据的套接字:由accept函数返回,用于与特定客户端收发数据。

所以在服务器端,我们需要封装两个类,就分别命名为:CTcpListenCTcpOfClient

  1. CTcpListen :用于监听等待客户端连接。
  2. CTcpOfClient:用于与连接上来的客户端进行收发信息。

注意,这两个类我都写在了头文件CNetServer.h中,之所以我要这样写,主要有两个原因:

  1. 这两个类中的代码并不多,并且两者联系也很紧密。
  2. 便于大家查看,因为如果两个类分开写,同时再将代码分离出来一个.cpp的源文件,一下子出现4个文件,大家可能就真不太好观察。

所以我这里将其写在了一个文件中,且代码并未分离,但你可以将其分离到对应的.cpp文件中。

首先需要的头文件以及库文件写好:

#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<string>
using std::string;

然后就先来写 CTcpOfClient吧,因为这个类会在CTcpListen 接受客户端连接的时候用到。

首先是成员变量,这里我添加了两个成员变量:

image-20231214145243439

  1. m_sock:用于和客户端通信的套接字。
  2. m_ip:用于保存客户端的ip地址。

套接字就是accept的返回值嘛,可以用于通信,而客户端的ip地址其实也返回到了accept的地址参数中,可通过特定函数获取,后面再提。

紧接着就是构造函数与析构函数。

构造函数用于将套接字置为无效,而析构函数则用于关闭套接字,通过析构函数,我们就可以省去关闭套接字的步骤。

紧接着就是设置这两个成员变量的函数:

image-20231214145332768

这个没啥可说的,就是将accept函数返回的信息,赋值给我们的成员变量。

然后还有一个获取ip的函数,以及最重要的两个函数收发数据函数:

image-20231214145412424

都很简单,就是调用一下最基本的收发数据函数,然后返回它们的返回值而已,但我们却可以少用两个参数。

因为这两个函数的最后一个参数都固定为0,第一个参数固定为成员变量m_sock,就不需要外面传递了。

至此,我们的收发数据的客户端套接字就封装好了,完整代码如下:

class CTcpOfClient
{
作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux