江苏省建设局官方网站查询,如何做弹幕视频网站,个人网页设计与实现论文免费,做网站用建站模版好还是定制好TCP网络模型的封装
最近学习了TCP网络模型的封装#xff0c;其中运用的封装技术个人感觉有点绕
在反复读代码、做思维导图下初步理解了这套封装模型#xff0c;不禁感叹原来代码还能这样写#xff1f;神奇#xff01;
为此将源码分享出来并将流程图画出#xff0c;方便…TCP网络模型的封装
最近学习了TCP网络模型的封装其中运用的封装技术个人感觉有点绕
在反复读代码、做思维导图下初步理解了这套封装模型不禁感叹原来代码还能这样写神奇
为此将源码分享出来并将流程图画出方便理解和复习 PS下列思维导图仅代表个人理解如有误恳请指出纠正 模型继承关系图
要理解该模型我认为首先要画图理解类的继承关系下面是我画的一个简单关系图
模型流程图
下面是我画的该模型的大致流程图仅供参考有误恳请指出
具体代码实现
EventLoop.hpp
#ifndef _EVENTLOOP_H_
#define _EVENTLOOP_H_#include list
#include WinSock2.henum class E_Event_Type
{Recv,Send,
};class IEventCallback
{
public:virtual void OnNetEvent(E_Event_Type e) 0;virtual void OnClose() 0;
};struct sSelectEvent
{SOCKET sock;IEventCallback* event;
};class EventLoop
{
private:std::listsSelectEvent* _events;std::listsSelectEvent* _delEventCaches;public:void LoopOnce();void AddEvent(sSelectEvent* e){_events.push_back(e);}void DelEvent(sSelectEvent* e);
};
#endif
EventLoop.cpp
#include EventLoop.hppvoid EventLoop::LoopOnce()
{fd_set reads;FD_ZERO(reads);do{auto begin _events.begin();auto end _events.end();for (; begin ! end; begin)FD_SET((*begin)-sock, reads);//(*begin)-event-NeedWrite()} while (false);int nSeclect select(0, reads, nullptr, nullptr, nullptr);if (0 nSeclect)return;if (nSeclect 0)return;do{auto begin _events.begin();auto end _events.end();for (; begin ! end; begin){if (FD_ISSET((*begin)-sock, reads)){(*begin)-event-OnNetEvent(E_Event_Type::Recv);}}} while (false);do{auto begin _delEventCaches.begin();auto end _delEventCaches.end();for (; begin ! end; begin){sSelectEvent* p *begin;_events.remove_if([p](sSelectEvent* a){return a p;});p-event-OnClose();}_delEventCaches.clear();} while (false);}void EventLoop::DelEvent(sSelectEvent* e)
{_delEventCaches.push_back(e);
}
TcpListen.hpp
#ifndef _TCPLISTEN_H_
#define _TCPLISTEN_H_
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include EventLoop.hpp
#include WinSock2.h
#include iostream
#include functional
class TcpSocket;
class TcpListen :public IEventCallback
{
protected:SOCKET _sock;sSelectEvent _event;EventLoop* _loop;std::functionTcpSocket* () _sockCB;
public:TcpListen();void Init(EventLoop* loop, std::functionTcpSocket* () sockCB){_loop loop; _sockCB sockCB;}bool Listen(unsigned short port, const char* const ip 0.0.0.0);// 通过 IEventCallback 继承virtual void OnNetEvent(E_Event_Type e) override;virtual void OnClose() override;
public:virtual void OnAccpet(TcpSocket* sock) 0;};
#endifTcpListen.cpp
#include TcpListen.h
#include TcpSocket.h
TcpListen::TcpListen()
{_event.event this;_sock _event.sock INVALID_SOCKET;_loop nullptr;
}bool TcpListen::Listen(unsigned short port, const char* const ip)
{_sock socket(AF_INET, SOCK_STREAM, 0);if (INVALID_SOCKET _sock){std::cout create SOCKET fail!\n std::endl;return false;}std::cout 1.create SOCKET OK!\n std::endl;// 2.绑定IP和端口
// bind(SOCKET,绑定的IP端口结构体,结构体大小)SOCKADDR_IN serverAddr;serverAddr.sin_family AF_INET;//SOCKADDR_IN6*serverAddr.sin_port htons(port);// 127.0.0.1 本机回环地址// 0.0.0.0 绑定所有IPserverAddr.sin_addr.s_addr inet_addr(ip);//SOCKADDR_IN6 serverAddr6;if (SOCKET_ERROR bind(_sock, (SOCKADDR*)serverAddr, sizeof(serverAddr))){std::cout bind SOCKET fail!\n std::endl;return false;}std::cout 2.bind SOCKET OK!\n std::endl;listen(_sock, 5);std::cout 3.listen SOCKET OK!\n std::endl;_event.sock _sock;_loop-AddEvent(_event);return true;
}void TcpListen::OnNetEvent(E_Event_Type e)
{SOCKADDR_IN clientAddr;int addrlen sizeof(SOCKADDR_IN);SOCKET clientSock accept(_sock, (SOCKADDR*)clientAddr, addrlen);if (INVALID_SOCKET clientSock){std::cout 4.ACCEPT ERROR!!\n std::endl;return;}std::cout 4.ACCEPT ip: inet_ntoa(clientAddr.sin_addr) Port: ntohs(clientAddr.sin_port) clientSock std::endl;TcpSocket* sock _sockCB();sock-OnAccept(clientSock, clientAddr);OnAccpet(sock);}void TcpListen::OnClose()
{
}TcpSocket.hpp
#ifndef _TCPSOCKET_H_
#define _TCPSOCKET_H_
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include EventLoop.hppconst unsigned int RECV_MAX_BUF 4096 * 2;class TcpSocket :public IEventCallback
{
private:SOCKET _sock;SOCKADDR_IN _addr;sSelectEvent _event;EventLoop* _loop;char _recvBuff[RECV_MAX_BUF];int _recvLen;bool _bClose;
public:TcpSocket();virtual ~TcpSocket();void Init(EventLoop* loop);void OnAccept(SOCKET sock, SOCKADDR_IN* addr);void Close();public:// 通过 IEventCallback 继承virtual void OnNetEvent(E_Event_Type e) override;virtual void OnClose() override;public:virtual int OnNetMsg(const char* const msg, int msgLen) 0;void Send(const char* msg, int msgLen);};#endif
TcpSocket.cpp
#include TcpSocket.hTcpSocket::TcpSocket()
{_sock _event.sock INVALID_SOCKET;_event.event this;_recvLen 0;_bClose false;
}TcpSocket::~TcpSocket()
{
}void TcpSocket::Init(EventLoop* loop)
{_loop loop;_loop-AddEvent(_event);
}void TcpSocket::OnAccept(SOCKET sock, SOCKADDR_IN* addr)
{_sock sock;_event.sock sock;memcpy(_addr, addr, sizeof(addr));
}void TcpSocket::Close()
{if (_bClose) return;_bClose true;_loop-DelEvent(_event);
}void TcpSocket::OnNetEvent(E_Event_Type e)
{if (E_Event_Type::Recv e){int nRecv recv(_sock, _recvBuff _recvLen, RECV_MAX_BUF - _recvLen, 0);if (nRecv 0){Close();return;}_recvLen nRecv;while (_recvLen ! 0){int nRet OnNetMsg(_recvBuff, _recvLen);if (nRet 0)break;_recvLen - nRet;for (int i 0; i _recvLen; i){_recvBuff[i] _recvBuff[i nRet];}}if (_recvLen RECV_MAX_BUF) Close();}
}void TcpSocket::OnClose()
{closesocket(_sock);delete this;
}void TcpSocket::Send(const char* msg, int msgLen)
{send(_sock, msg, msgLen, 0);
}
EasyTcpServer.cpp
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include iostream#include WinSock2.h
#pragma comment(lib,ws2_32)
#include vector#include TcpListen.h
#include TcpSocket.hclass EasyTcpClient :public TcpSocket
{
public:// 通过 TcpSocket 继承virtual int OnNetMsg(const char* const msg, int msgLen) override{std::cout msgLen 接受客户端数据: msg std::endl;return msgLen;}
};class EasyTcpServer :public TcpListen
{
public:void OnAccpet(TcpSocket* sock) override{//sock-Init(_loop)sock-Init(_loop);std::cout 客户端连接 std::endl;}};int main()
{// 加载网络环境WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), wsaData);EventLoop loop;EasyTcpServer listen;listen.Init(loop, []()-TcpSocket*{return new EasyTcpClient;});listen.Listen(7890);while (true){loop.LoopOnce();}return 0;
}最后
void OnAccpet(TcpSocket* sock) override
{//sock-Init(_loop)sock-Init(_loop);std::cout 客户端连接 std::endl;
}};
int main() { // 加载网络环境 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), wsaData);
EventLoop loop;EasyTcpServer listen;listen.Init(loop, []()-TcpSocket*{return new EasyTcpClient;});listen.Listen(7890);while (true)
{loop.LoopOnce();
}return 0;}
# 最后代码经供参考如有疑问或者代码有问题欢迎提出