[C++]sylar高性能服务器框架学习记录:TCPServer模块

记录一下最近这学期学习的sylar服务器框架项目,输出整理一下项目的结构,用到的知识和自己的体会

项目仓库地址

https://github.com/sylar-yin/sylar/

整理博客过程中参考的大佬资料链接:

============================================

基础介绍

封装了一个TCP服务器,支持绑定多端口监听,支持分别指定用于监听的调度器和用于处理连接的调度器

默认handleClient方法会返回最简单的http1.1报文,内容是hello,子类可重载handleClient方法

class TcpServer : public std::enable_shared_from_this
<TcpServer>
                , Noncopyable {
public:
    typedef std::shared_ptr
<TcpServer> ptr;
    TcpServer(sylar::IOManager* worker = sylar::IOManager::GetThis(),
              sylar::IOManager* accept_worker = sylar::IOManager::GetThis());
    virtual ~TcpServer();

    virtual bool bind(sylar::Address::ptr addr);                // 绑定单个地址
    virtual bool bind(const std::vector<Address::ptr>& addrs,   // 绑定多个地址
                      std::vector<Address::ptr>& fails);
    virtual bool start();       // 启动
    virtual void stop();        // 停止

    uint64_t getRecvTimeout() const { return m_recvTimeout; }
    std::string getName() const { return m_name; }
    void setRecvTimeout(uint64_t v) { m_recvTimeout = v; }
    void setName(const std::string& v) { m_name = v; }

    bool isStop() const { return m_isStop; }

protected:
    virtual void handleClient(Socket::ptr client);      // 处理客户端
    virtual void startAccept(Socket::ptr sock);         // 开始接收连接

protected:
    std::vector<Socket::ptr> m_socks;   // 多监听多网卡
    IOManager* m_worker;                // 新连接的socket工作的调度器
    IOManager* m_acceptworker;          // 服务器监听socket接收连接的调度器
    uint64_t m_recvTimeout;             // 接收超时时间
    std::string m_name;                 // 服务器名称
    std::string m_type = "tcp";         // 服务器类型
    bool m_isStop;                      // 服务器是否停止

};

构造/析构函数

TcpServer::TcpServer(sylar::IOManager* worker, sylar::IOManager* accept_worker)
    : m_worker(worker)
    , m_acceptworker(accept_worker)
    , m_recvTimeout(g_tcp_server_read_timeout->getValue())
    , m_name("sylar/1.0.0")
    , m_isStop(true) {
}

TcpServer::~TcpServer() {
    for(auto& i : m_socks) {
        i->close();
    }
    m_socks.clear();
}

绑定监听地址

bool TcpServer::bind(sylar::Address::ptr addr) {
    std::vector<Address::ptr> addrs;
    std::vector<Address::ptr> fails;
    addrs.push_back(addr);
    return bind(addrs, fails);
}

bool TcpServer::bind(const std::vector<Address::ptr>& addrs,
                     std::vector<Address::ptr>& fails) {
    // 遍历传入的要绑定的监听地址
    for(auto& addr : addrs) {
        // 创建TCPsocket
        Socket::ptr sock = Socket::CreateTCP(addr);
        // bind
        if(!sock->bind(addr)) {
            SYLAR_LOG_ERROR(g_logger) << "bind fail errno="
                << errno << " errstr=" << strerror(errno)
                << " addr=[" << addr->toString() << "]";
            // 收集绑定失败的地址
            fails.push_back(addr);
            continue;
        }
        // 设置监听
        if(!sock->listen()) {
            SYLAR_LOG_ERROR(g_logger) << "listen fail errno="
                << errno << " errstr=" << strerror(errno)
                << " addr=[" << addr->toString() << "]";
            // 收集设置监听失败的地址
            fails.push_back(addr);
            continue;
        }
        // 绑定监听完成,加入数组
        m_socks.push_back(sock);
    }

    if(!fails.empty()) {
        m_socks.clear();
        return false;
    }

    // 若没有失败,打印日志
    for(auto& i : m_socks) {
        SYLAR_LOG_INFO(g_logger) << "sever bind success: " << *i;
    }
    return true;
}

开启/关闭服务器

bool TcpServer::start() {
    if(!m_isStop) {
        return true;
    }
    m_isStop = false;
    // 调度每个监听socket的接收任务
    for(auto& sock : m_socks) {
        m_acceptworker->schedule(std::bind(&TcpServer::startAccept,
                            shared_from_this(), sock));
    }
    return true;
}

void TcpServer::stop() {
    m_isStop = true;
    auto self = shared_from_this();
    // 将this和self作为参数传递给异步任务的Lambda函数,确保异步任务执行期间,当前对象的shared_ptr一直有效
    m_acceptworker->schedule([this, self]() {
        for(auto& sock : m_socks) {
            sock->cancelAll();
            sock->close();
        }
        m_socks.clear();
    });
}

accept工作循环

void TcpServer::startAccept(Socket::ptr sock) {
    // 工作循环
    while(!m_isStop) {
        // 调用accept(已被hook)
        Socket::ptr client = sock->accept();
        // 如果连接成功
        if(client) {
            // 打印日志
            SYLAR_LOG_INFO(g_logger) << "sock=" << *client << "connected";
            // 设置接收超时时间
            client->setRecvTimeout(m_recvTimeout);
            // 在工作调度器上为每个连接成功的socket调度handleClient
            // handleClient结束之前,TCPServer不能结束
            m_worker->schedule(std::bind(&TcpServer::handleClient,
                        shared_from_this(), client));
        } else {
            SYLAR_LOG_ERROR(g_logger) << "accept errno=" << errno
                        << "errstr=" << strerror(errno);
        }
    }
}

handleClient方法

默认发回hello报文

void TcpServer::handleClient(Socket::ptr client) {
    SYLAR_LOG_INFO(g_logger) << "handle client: " << *client;
    const char* rsp =
        "HTTP/1.1 200 OK\r\n"
        "Content-Length: 5\r\n"
        "\r\n"
        "hello";
    client->send(rsp, strlen(rsp));
}

测试

监听localhost的8033端口

#include "sylar/tcp_server.h"
#include "sylar/iomanager.h"
#include "sylar/log.h"

static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();

void run() {
    auto addr = sylar::Address::LookupAny("0.0.0.0:8033");
    // auto addr2 = sylar::UnixAddress::ptr(new sylar::UnixAddress("/tmp/unix_addr"));
    std::vector<sylar::Address::ptr> addrs;
    addrs.push_back(addr);
    // addrs.push_back(addr2);

    sylar::TcpServer::ptr tcp_server(new sylar::TcpServer);
    std::vector<sylar::Address::ptr> fails;

    // ::unlink("/tmp/unix_addr");

    while(!tcp_server->bind(addrs, fails)) {
        sleep(2);
    }
    tcp_server->start();
}

int main(int argc, char** argv) {
    sylar::IOManager iom(2);
    iom.schedule(run);
    return 0;
}

服务器开启,等待连接

image-20260310235324286

使用curl向服务器发送请求,可以看到返回了hello,服务器也打印了连接信息

image-20260310235419460

image-20260310235451532

总结

之后写HttpServer可以继承该TcpServer类

评论

  1. sankkooos
    Android Chrome 142.0.7444.173
    2 周前
    2026-3-11 18:31:19

    严肃观看中……୧(๑•̀⌄•́๑)૭

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇