(二)libevent库的使用

参考:

1. libevent

使用第三方库我一般都偏爱最新的版本,libevent也是如此,所以我以 libevent-2.1.8-stable.tar.gz为例,在官网上可以下载。

编译、使用

./configure
make

头文件在include文件夹下,编译生成的动态库在.libs文件夹下。
1401565-20180801195711005-1747520049.jpg

使用时,需要包含头文件和连接libevent.so动态库。

2. 示例

2.1 TcpServer.h

#ifndef TCP_SERVER_H
#define TCP_SERVER_H

struct event_base;

class TcpServer
{
public:
    using callback = void(int, short, void*);
    //typedef void (callback)(int, short, void*);

public:
    TcpServer(const int port);
    ~TcpServer();

    int Initialize();

    int Start();

    void Process();

private:
    int m_fd;
    int m_port;
    event_base* m_base;
    callback *m_accept_callback;
};

#endif  // TCP_SERVER_H

2.2 TcpServer.cpp

#include "TcpServer.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <string>

#include "libevent/event.h"


void accept_cb(int fd, short events, void* arg)
{
    struct sockaddr_in client;
    socklen_t len = sizeof(client);

    int sockfd = ::accept(fd, (struct sockaddr*)&client, &len );
    if(sockfd < 0){
        return;
    }

    /* 提取客户端IP地址 */
    char  szIP[64]  = { 0 };   // 客户端IP地址
    std::string strIP = inet_ntop(AF_INET, &client.sin_addr, szIP, sizeof(szIP));
    printf("connect from client: %s\n", strIP.c_str());

    TcpServer *pServer = static_cast<TcpServer*>(arg);
    pServer->Process(sockfd);

    close(sockfd);
    printf("close\n");
}


TcpServer::TcpServer(const int port):
    m_fd(-1),
    m_port(port),
    m_base(nullptr),
    m_accept_callback(nullptr)
    {
        m_accept_callback = accept_cb;
    }

TcpServer::~TcpServer()
{
    close(m_fd);
}

int TcpServer::Initialize()
{
    m_fd = ::socket(AF_INET, SOCK_STREAM, 0);
    if( m_fd == -1 )
        return -1;

    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = 0;
    sin.sin_port = htons(m_port);

    int flag = 1;
    socklen_t len = sizeof(flag);
    if(::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) < 0)
    {
        return -4;
    }

    if( ::bind(m_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0 )
    {
        return -2;
    }

    if( ::listen(m_fd, 10) < 0)
    {
        return -3;
    }

    return 0;
}

int TcpServer::Start()
{
    m_base = event_base_new();
    if(nullptr == m_base)
    {
        return -4;
    }

    //添加监听客户端请求连接事件  
    struct event* ev_listen = event_new(m_base, m_fd, EV_READ | EV_PERSIST,
                                        m_accept_callback, this);
    event_add(ev_listen, NULL);

    event_base_dispatch(m_base);

    return 0;
}

void TcpServer::Process(int fd)
{
    printf("process...\n");

    char msg[4096];  
    int len = read(fd, msg, sizeof(msg) - 1);
    if( len <= 0 )
    {
        printf("some error happen when read\n");
        return ;
    }
    printf("%s",msg);

    if(strcmp(msg,"get stats") != 0)
    {
        // return;
    }

    // {'stat':'1', 'version':'${project.name}-V${project.version}-B${SVN.revision}'}
    char reply_msg[4096] = "{'stat':'1', 'version':'middleware-V1.0.0-B12965'}";
    write(fd, reply_msg, strlen(reply_msg) );
}

2.3 main.cpp

#include "TcpServer.h"

// #include <unistd.h>
#include <memory>
#include <iostream>
using namespace std;

int main()
{
    shared_ptr<TcpServer> spServer = make_shared<TcpServer>(999);
    int ret = 0;
    ret = spServer->Initialize();j
    if (ret != 0){
        std::cout<<"initialize failed "<<ret<<std::endl;
    }
    spServer->Start();

    // while(true)
    // {
    //  sleep(1);
    // }
    return 0;
}

2.4 CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project(demo)

# 设置编译器(gcc/g++)
set(CMAKE_CXX_COMPILER "g++")

#设置Debug/Release
set(CMAKE_BUILD_TYPE "Debug")

# 设置编译选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -g -Wall")

# 设置可执行二进制文件的目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 设置存放编译出来的库文件的目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 并把该目录设置为链接目录
link_directories(${PROJECT_SOURCE_DIR}/lib)

# 设定头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 增加子文件夹(src路径是通过子文件夹形式添加)
add_subdirectory(${PROJECT_SOURCE_DIR}/src)
# 编译静态、动态链接库
add_library(TcpServer SHARED TcpServer.cpp)
target_link_libraries(TcpServer libevent.so)

# 编译可执行文件和设置链接库(注意顺序)
add_executable(main main.cpp)
target_link_libraries(main libTcpServer.so)

2.5 测试

可以通过curl命令来查看是否可以连接服务器

curl http://ip:port

或者telnet命令来检查

[root@thor ~]# telnet 127.0.0.1 999
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get stats
{'stat':'1', 'version':'middleware-V1.0.0-B12965'}Connection closed by foreign host.

转载于:https://www.cnblogs.com/walkinginthesun/p/9403648.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据操作、用户权限管理等关键技术。 数据设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据设计文件。这些文件通常包括数据结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值