更改编码格式以下使用VS2022进行演示。
在使用vs2022书写服务端的时候,最好将编码格式改为utf-8,下面介绍如果在vs2022中进行快速设置文件的编码格式。
首先使用vs2022打开某个项目,点击工具=》自定义模块。
紧接着选择:命令=》添加命令。
滑动滚动条找到:文件=》高级保存选项=》确定。即可。
之后我们会发现我们vs2022编译器左上方会出现该窗口。
最后,我们点击该按钮,更改编码格式即可。
EventLoop框架效果展示TIPS:这里暂时不过多的叙述EventLoop框架的概念,下面主要是实操代码。
目录结构TIPS:客户端使用sokit工具进行演示。有两个服务端加入到事件循环机制中进行监听消息,端口号分别为7890和7891。功能仅仅只是客户端成功连接后响应相应的事件。
#ifndef UNETCORE_H_ #define UNETCORE_H_ //表示当前IO内核使用的是select模型 #define U_SELECT_NETCORE #define _WINSOCK_DEPRECATED_NO_WARNINGS #includeEventLoop.hnamespace U { //EventLoop抽象类,事件循环机制 class IEventLoop { public: virtual void Init() = 0; virtual void LoopOnce() = 0; virtual void UnInit() = 0; }; //用于管理连接上来的客户端 //TODO class ITcpSocket { virtual void Init(IEventLoop* loop) = 0; }; //响应客户端连接回调函数 typedef std::function FTcpServerCB; //ITcpServer抽象类,服务端 class ITcpServer { public: /// /// 初始化TCP服务,与循环事件进行关联 /// /// 事件循环机制 /// 当用户连接成功后的回调函数 ///virtual bool Init(IEventLoop* loop, FTcpServerCB cb) = 0; /// /// 初始化socket /// /// 服务端IP /// 监听端口号 ///错误返回false virtual bool Listen(const char* ip, int port) = 0; }; //加载Windows网络库 void InitNetCore(); //卸载Windows网络库 void UnNetCore(); //实例化事件循环机制 IEventLoop* CreateEventLoop(); //实例化服务端类 ITcpServer* CreateTcpServer(); } #endif // !UNETCORE_H_
#include "UNetCore.h" #ifdef U_SELECT_NETCORE #includeEventLoop.cpp#include #include #pragma comment(lib,"ws2_32") #ifndef EVENTLOOP_H_ #define EVENTLOOP_H_ namespace U { //保存服务端单元的信息。即与服务端句柄关联,保存至事件循环机制中 class sEvent { public: //该服务端是属于什么类型的(TCP、UDP、PIPE) enum class Type { E_TCPSERVER, //UDP,PIPE }; Type type; SOCKET sock;//保存服务端句柄 //由于sEvent类必须要附带服务端类,那么如果不使用联合体,会造成过度的内存资源浪费,即这里使用联合体保存各种类型服务端类的指针。 union { class TcpServer* tcpServer; //class UcpServer* ucpServer; //... }; }; class EventLoop :public IEventLoop { private: std::unordered_map _events; public: void Init() override; void LoopOnce() override; void UnInit() override; //添加监听的循环事件,压入sEvent单元 void AddEvent(sEvent* event); }; } #endif // !EVENTLOOP_H_ #endif // U_SELECT_NETCORE
#include "EventLoop.h"
#include "TcpServer.h"
#ifdef U_SELECT_NETCORE
namespace U
{
void InitNetCore()
{
WSADATA wsa;
WSAStartup(MAKEWORd(2, 2), &wsa);
//TODO 可以添加异常导出库,在程序崩溃生成崩溃信息
}
void UnNetCore()
{
WSACleanup();
}
IEventLoop* CreateEventLoop()
{
return new EventLoop;
}
}
void U::EventLoop::Init()
{
}
//采用select IO模型
void U::EventLoop::LoopOnce()
{
FD_SET reads;
FD_ZERO(&reads);
for (auto& event : _events)
FD_SET(event.first, &reads);
int nRet = select(0, &reads, nullptr, nullptr, nullptr);
if (nRet <= 0)
return;
for (auto& event : _events)
{
SOCKET sock = event.first;
sEvent* pEvent = event.second;
if (FD_ISSET(sock, &reads))
{
switch (pEvent->type)
{
case U::sEvent::Type::E_TCPSERVER://处理TCP类的服务端
{
pEvent->tcpServer->OnAccept();
break;
}
default:
break;
}
}
}
}
void U::EventLoop::UnInit()
{
}
void U::EventLoop::AddEvent(sEvent* event)
{
std::cout << "添加 事件" << event->sock
<< " type:" << (int)event->type
<< " serverPtr:" << event->tcpServer
<< std::endl;
_events.insert(std::make_pair(event->sock, event));
}
#endif // U_SELECT_NETCORE
TcpServer.h
#include "UNetCore.h"
#ifdef U_SELECT_NETCORE
#include "EventLoop.h"
#ifndef TCPSERVER_H_
#define TCPSERVER_H_
namespace U
{
class TcpServer :public ITcpServer
{
private:
EventLoop* _loop;//事件循环机制
FTcpServerCB _cb;//客户端连接回调事件
SOCKET _sock;//服务端socket
sEvent _event;//往事件循环机制注册消息的最小单元,即用于注册循环事件
public:
TcpServer();
~TcpServer();
bool Init(IEventLoop* loop, FTcpServerCB cb) override;
bool Listen(const char* ip, int port) override;
public:
//处理客户端连接
void OnAccept();
};
}
#endif // !TCPSERVER_H_
#endif // U_SELECT_NETCORE
TcpServer.cpp
#include "TcpServer.h"
#ifdef U_SELECT_NETCORE
namespace U
{
ITcpServer* CreateTcpServer()
{
return new TcpServer;
}
}
U::TcpServer::TcpServer()
{
std::cout << "初始化 TCPServer " << std::endl;
_loop = nullptr;
_cb = nullptr;
_sock = INVALID_SOCKET;
_event.tcpServer = this;
_event.type = U::sEvent::Type::E_TCPSERVER;
_event.sock = INVALID_SOCKET;
}
U::TcpServer::~TcpServer()
{
_loop = nullptr;
_cb = nullptr;
if (INVALID_SOCKET != _sock)
closesocket(_sock);
_sock = INVALID_SOCKET;
}
bool U::TcpServer::Init(IEventLoop* loop, FTcpServerCB cb)
{
_loop = dynamic_cast(loop);
_cb = cb;
return true;
}
bool U::TcpServer::Listen(const char* ip, int port)
{
std::cout << "Listen IP:" << ip << " port:" << port << std::endl;
//TODO 待完善
if (_sock != INVALID_SOCKET)
{
closesocket(_sock);
return false;
}
_sock = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
if (SOCKET_ERROR == bind(_sock, (sockaddr*)&addr, sizeof(addr)))
return false;
if (SOCKET_ERROR == listen(_sock, 5))
return false;
_event.sock = _sock;
_loop->AddEvent(&_event);
return true;
}
void U::TcpServer::OnAccept()
{
//TODO 未处理客户端socket(句柄)
SOCKADDR_IN addr;
int addrLen = sizeof(SOCKADDR_IN);
SOCKET sock = accept(_sock, (sockaddr*)&addr, &addrLen);
//连接成功后调用回调函数
_cb(nullptr);
}
#endif // U_SELECT_NETCORE
UServer.cpp
#include "UNetCore.h" #includeint main() { //加载Windows网络库 U::InitNetCore(); //调用EventLoop循环机制 U::IEventLoop* loop = U::CreateEventLoop(); //开启两个服务端 U::ITcpServer* server = U::CreateTcpServer(); U::ITcpServer* server1 = U::CreateTcpServer(); //将服务端与事件循环机制loop关联 server->Init(loop, [](U::ITcpSocket* sock) { std::cout << "客户端1连接" << std::endl; }); server1->Init(loop, [](U::ITcpSocket* sock) { std::cout << "客户端2连接" << std::endl; }); server->Listen("0.0.0.0", 7890); server1->Listen("0.0.0.0", 7891); //启动循环机制监听消息 while (true) loop->LoopOnce(); //卸载Windows网络库 U::UnNetCore(); return 0; }



