1.本章说明
前面一章我们已经学会了如何用C/C++语言进行网络编程,但那却仅限于最简单的一对一聊天,和我们平时用的QQ、微信的功能也差太多了。
所以本章将结合前面学到的MFC界面编程的知识,带领大家开发一个聊天软件,它的主要功能就是群聊。
本文项目源码的链接放在了文章末,需要的可以自取,如果觉得困难的,可以直接参照源码对照本文学习即可。
如果需要添加更多强大的功能,比如单聊、文件传输等等,可以参考另外两篇文章:
2.聊天室服务器
2.1 建立项目
聊天最重要的是什么?那当然是信息正确性,即对方是否收到了正确的信息,为了这个目的,那当然就是选择TCP协议了,因为它的特点之一就是可靠性!
而UDP协议主要运用于视频传输中,比如打微信视频,网不好的时候就会出现卡顿、丢帧,但这也并不是太影响整体的交流过程。
其次就是服务器形式,服务器仅仅只是用于转发信息而已,那自然是用不着图形化界面的,建立一个控制台项目即可。
过程相信大家都会了,那我也就不再演示如何建立一个项目了,我这里新建的一个解决方案名字为LANChat
,然后服务器项目的名称为LANServer
,客户端的先不用管,后面我再进行讲解:
然后服务器里面只有两个文件,首先是server.cpp
文件,这是这个服务器主要且唯一的源文件,main
函数入口在里面。
然后还有一个头文件名字为CNetServer.h
,这个用于我们封装类,便于使用,下面就要开始进行讲解。
2.2 封装套接字
上一章使用了TCP来进行服务器与客户端进行聊天的时候,我们发现很多步骤其实都是固定的,但每次却又不得不写,会相当的麻烦,比如初始化网络环境这一步骤。
所以为了更加有效率的开发软件,以及理解类的作用,首先我们要开始进行封装。
考虑到服务器端是需要两种套接字的:
- 监听套接字:等待客户端的连接。
- 收发数据的套接字:由
accept
函数返回,用于与特定客户端收发数据。
所以在服务器端,我们需要封装两个类,就分别命名为:CTcpListen
、CTcpOfClient
CTcpListen
:用于监听等待客户端连接。CTcpOfClient
:用于与连接上来的客户端进行收发信息。
注意,这两个类我都写在了头文件CNetServer.h
中,之所以我要这样写,主要有两个原因:
- 这两个类中的代码并不多,并且两者联系也很紧密。
- 便于大家查看,因为如果两个类分开写,同时再将代码分离出来一个
.cpp
的源文件,一下子出现4个文件,大家可能就真不太好观察。
所以我这里将其写在了一个文件中,且代码并未分离,但你可以将其分离到对应的.cpp
文件中。
首先需要的头文件以及库文件写好:
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<string>
using std::string;
然后就先来写 CTcpOfClient
吧,因为这个类会在CTcpListen
接受客户端连接的时候用到。
首先是成员变量,这里我添加了两个成员变量:
m_sock
:用于和客户端通信的套接字。m_ip
:用于保存客户端的ip地址。
套接字就是accept
的返回值嘛,可以用于通信,而客户端的ip地址其实也返回到了accept
的地址参数中,可通过特定函数获取,后面再提。
紧接着就是构造函数与析构函数。
构造函数用于将套接字置为无效,而析构函数则用于关闭套接字,通过析构函数,我们就可以省去关闭套接字的步骤。
紧接着就是设置这两个成员变量的函数:
这个没啥可说的,就是将accept
函数返回的信息,赋值给我们的成员变量。
然后还有一个获取ip的函数,以及最重要的两个函数收发数据函数:
都很简单,就是调用一下最基本的收发数据函数,然后返回它们的返回值而已,但我们却可以少用两个参数。
因为这两个函数的最后一个参数都固定为0
,第一个参数固定为成员变量m_sock
,就不需要外面传递了。
至此,我们的收发数据的客户端套接字就封装好了,完整代码如下:
class CTcpOfClient
{