Tìm hiểu mã nguồn brynet - Thành phần mạng

1. EventLoop.hpp

Lớp này đóng vai trò theo dõi socket và lập lịch tác vụ. Dưới đây là các biến thành viên chính:


// Mảng chứa sự kiện từ epoll_wait
std::vector danhSachSuKien;
// File descriptor của epoll
int epollFd;
// Kênh đánh thức epoll_wait
std::unique_ptr kenhDanhThuc;
// Trạng thái luồng
std::atomic_bool dangChoi;
std::atomic_bool daDanhThuc;
// Danh sách hàm bất đồng bộ
std::mutex khoaDanhSachHam;
std::vector<UserFunctor> danhSachHamAsync;
std::vector<UserFunctor> danhSachHamSaoChep;
// Hàm thực thi sau khi epoll_wait
std::vector<UserFunctor> danhSachHamSauLoop;
// Thông tin luồng
std::once_flag coKhoiTaoID;
std::atomic_bool daKhoiTaoID;
current_thread::THREAD_ID_TYPE idLuong;
// Bộ quản lý định thời
brynet::base::TimerMgr::Ptr boDinhThoi;
// Ánh xạ socket và kết nối
std::unordered_map danhSachKetNoi;

Hàm vòng lặp chính


void vongLap(int64_t miliGiay)
{
    khoiTaoIDLuong();
    kiemTraLuong();
    
    if (!danhSachHamSauLoop.empty())
    {
        miliGiay = 0;
    }
    
    int soLuong = epoll_wait(epollFd, danhSachSuKien.data(), danhSachSuKien.size(), miliGiay);
    dangChoi = false;

    for (int i = 0; i < soLuong; ++i)
    {
        auto kenh = (Channel*) (danhSachSuKien[i].data.ptr);
        auto suKien = danhSachSuKien[i].events;
        
        if (suKien & EPOLLRDHUP)
        {
            kenh->nhanDuLieu(true);
            kenh->dongKetNoi();
            continue;
        }

        if (suKien & EPOLLIN)
        {
            kenh->nhanDuLieu(false);
        }

        if (suKien & EPOLLOUT)
        {
            kenh->guiDuLieu();
        }
    }
    
    daDanhThuc = false;
    dangChoi = true;
    
    xuLyHamAsync();
    xuLyHamSauLoop();

    if (soLuong == danhSachSuKien.size())
    {
        dieuChinhKichThuoc(danhSachSuKien.size() + 128);
    }
    
    boDinhThoi->thucHien();
}

2. TcpConnection.hpp

Lớp quản lý phiên kết nối TCP với các callback sau:


// Callback khi kết nối thành công
using EnterCallback = std::function;
// Callback nhận dữ liệu
using DataCallback = std::function;
// Callback ngắt kết nối
using DisconnectedCallback = std::function;
// Callback sau khi gửi dữ liệu
using PacketSendedCallback = std::function;
// Callback khi vượt mức dữ liệu
using HighWaterCallback = std::function;

Hàm xử lý dữ liệu


void xuLyDuLieuNhan()
{
    if (hamXuLyDuLieu != nullptr && demNhan.coDuLieu())
    {
        auto docGia = brynet::base::BasePacketReader(demNhan.layConTro(), demNhan.layDoDai());
        hamXuLyDuLieu(docGia);
        
        size_t daXuLy = docGia.layViTri();
        demNhan.tienConTro(daXuLy);
    }
}

3. TCPServiceDetail.hpp

Hàm khởi tạo luồng worker


std::vector khoiTaoLuongWorker(size_t soLuong, FrameCallback ham = nullptr)
{
    std::vector vongLap;
    auto coChay = std::make_shared<bool>(true);
    
    auto wg = brynet::base::WaitGroup::Tao();
    for (int i = 0; i < soLuong; ++i)
    {
        auto vongLapMoi = std::make_shared<EventLoop>();
        vongLap.push_back(vongLapMoi);
        
        wg->them(1);
        vongLapDuLieu.push_back(IOLoopData::Tao(vongLapMoi, 
            std::make_shared([=]() {
                vongLapMoi->ganLuongHienTai();
                wg->hoanTat();
                
                while (*coChay)
                {
                    vongLapMoi->vongLap(sThoiGianMacDinh);
                    if (ham != nullptr)
                    {
                        ham(vongLapMoi);
                    }
                }
            })));
    }
    
    wg->cho();
    return vongLap;
}

Thẻ: C++ Networking event loop Socket Programming TCP/IP

Đăng vào ngày 7 tháng 7 lúc 17:39