📢博客主頁:https://blog.csdn.net/2301_779549673
📢博客倉庫:https://gitee.com/JohnKingW/linux_test/tree/master/lesson
📢歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請指正!
📢本文由 JohnKi 原創,首發于 CSDN🙉
📢未來很長,值得我們全力奔赴更美好的生活?
文章目錄
- 🏳??🌈一、TcpService.hpp
- 1.1 TcpService類
- 1.2 構造、析構函數
- 1.3 Loop() 循環函數
- 🏳??🌈二、Service.hpp
- 2.1、IOService類基本結構
- 2.2 構造函數、析構函數
- 2.3 IOSExcute()
- 🏳??🌈三、TcpServer.cpp
- 👥總結
上一篇文章簡單的將 Socket
類進行了封裝,封裝的目的是為了我們后序直接使用的,因此這篇文章使用封裝好的Socket類實現網絡計算器(加協議版本)的一部分輪廓,此處我們將執行方法單獨放在一個文件!
🏳??🌈一、TcpService.hpp
我們這里使用 TcpServer 的多線程版本,如有其他版本的需要,可移步 傳送門
1.1 TcpService類
TcpServer類成員變量有端口號,監聽套接字(封裝的智能指針類型),運行狀態和執行方法,構造函數初始化成員變量即可!
namespace TcpServerModule{using namespace SocketModule;using namespace LogModule;using service_t = std::function<void(SocketModule::SockPtr, InetAddr&)>;class TcpServer{public:TcpServer(service_t service, uint16_t port){}void Loop(){}~TcpServer(){}private:uint16_t port;SockPtr _listensock;bool _isrunning;service_t _service;};
}
1.2 構造、析構函數
構造函數初始化成員變量并創建監聽套接字(調用父類方法),析構函數無需處理!
TcpServer(service_t service, uint16_t port): _port(port), _listensock(std::make_shared<TcpSocket>()),_isrunning(false), _service(service) {_listensock->BuildListenSocket(port);
}
~TcpServer() {}
1.3 Loop() 循環函數
Loop()函數使用多線程的版本執行長服務,讓新線程去執行主函數傳遞的執行方法!
void Loop() {_isrunning = true;while (_isrunning) {InetAddr client;// 獲取客戶端連接SockPtr cli = _listensock->Accepter(&client);if (cli == nullptr)continue;LOG(LogLevel::DEBUG)<< "get a new connection from " << client.AddrStr().c_str();// 獲取成功pthread_t tid;// ThreadData 的頭文件是ThreadData* td = new ThreadData(cli, this, client);pthread_create(&tid, nullptr, Execute, td); // 新線程分離}
}
// 線程函數參數對象
class ThreadData {
public:SockPtr _sockfd;TcpServer* _self;InetAddr _addr;public:ThreadData(SockPtr sockfd, TcpServer* self, const InetAddr& addr): _sockfd(sockfd), _self(self), _addr(addr) {}
};
// 線程函數
static void* Execute(void* args) {ThreadData* td = static_cast<ThreadData*>(args);// 子線程結束后由系統自動回收資源,無需主線程調用 pthread_joinpthread_detach(pthread_self()); // 分離新線程,無需主線程回收td->_self->_service(td->_sockfd, td->_addr);delete td;return nullptr;
}
🏳??🌈二、Service.hpp
該文件設計一個類,其中一個成員函數實現執行方法,暫時先讓服務端代碼編譯過即可,后序再加協議!
2.1、IOService類基本結構
class IOService{public:IOService();void IOExcute(SockPtr sock, InetAddr& addr);~IOService();
};
2.2 構造函數、析構函數
這個類沒有成員變量,所以這兩部分不需要處理
2.3 IOSExcute()
該函數時
TcpServer
中執行方法的具體實現,此處暫時只進行IO操作,保證編譯通過
void IOExcute(SockPtr sock, InetAddr& addr) {while (true) {std::string message;// ssize_t Recv(std::string* out) override{}ssize_t n = sock->Recv(&message);if (n > 0) {LOG(LogLevel::INFO) << "get message: " << message << "from"<< addr.AddrStr().c_str();std::string rsp = "response test";sock->Send(rsp);} else if (n == 0) {LOG(LogLevel::INFO)<< "client " << addr.AddrStr().c_str() << " disconnected";break;} else {LOG(LogLevel::ERROR)<< "recv error for client: " << addr.AddrStr().c_str();break;}}
}
🏳??🌈三、TcpServer.cpp
創建TcpServer類對象,并調用執行函數運行服務端!
#include "TcpServer.hpp"
#include "Service.hpp"using namespace TcpServerModule;int main(int argc, char* argv[]){if(argc != 2){std::cerr << "Usage: " << argv[0] << " port" << std::endl;Die(1);}uint16_t port = std::stoi(argv[1]);IOService service;std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(std::bind(&IOService::IOExcute, &service, std::placeholders::_1, std::placeholders::_2),port);tsvr->Loop();return 0;
}
👥總結
本篇博文對 【Linux網絡】TCP服務中IOService應用與實現 做了一個較為詳細的介紹,不知道對你有沒有幫助呢
覺得博主寫得還不錯的三連支持下吧!會繼續努力的~