【Linux网络】TCP服务中IOService应用与实现

📢博客主页:https://blog.csdn.net/2301_779549673

📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

📢本文由 JohnKi 原创,首发于 CSDN🙉

📢未来很长,值得我们全力奔赴更美好的生活✨

文章目录


上一篇文章简单的将 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_join
    pthread_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应用与实现 做了一个较为详细的介绍,不知道对你有没有帮助呢

觉得博主写得还不错的三连支持下吧!会继续努力的~

相关推荐
逐梦吧!旅行者1 天前
Linux之环境变量(内容由浅入深,层层递进)
linux·运维
IOT-Power1 天前
树莓派 Ubuntu 24.04 开机换源总结
linux·数据库·ubuntu
weixin_468466851 天前
树莓派32位与64位系统安装teamviewer远程软件
linux·单片机·自动化·树莓派·远程控制·vnc·teamviewer
挨踢攻城1 天前
Linux 应急响应实操 Checklist
linux·运维·linux命令·rhce·rhca·厦门微思网络·linux 应急响应
wanhengidc1 天前
什么是云手机?
运维·网络·安全·游戏·智能手机
optiz1 天前
细菌基因组genome二代测序数据分析
linux·运维·服务器
机器人梦想家1 天前
pymodbus启动一个简单的modbus tcp server
网络·网络协议·tcp/ip
一刀到底2111 天前
springboot3.3.5 集成elasticsearch8.12.2 ssl 通过 SSL bundle name 来实现
网络·elasticsearch·ssl·springboot3
m0_661316231 天前
modbus_tcp和modbus_rtu对比&移植AT-socket,modbus_tcp&杂记
服务器·网络·tcp/ip
李游Leo1 天前
LaTeX TeX Live 安装与 CTAN 国内镜像配置(Windows / macOS / Linux 全流程)
linux·windows·macos