sol_socket详解

一、概述

sol_socket是一种基于事件驱动的网络I/O库,它能够在不同的平台上提供高性能、高可靠性的网络通信。sol_socket是一个轻型的库,它的核心是使用非阻塞I/O和事件通知处理I/O读写事件。sol_socket封装了socket系统调用和网络事件处理模型,提供了方便的编程接口。

二、基本使用

在使用sol_socket前,需要先建立一个event_base(事件处理器)对象、一个或多个event(事件)对象。

struct event_base* base = event_base_new();
struct event* ev = event_new(base, sock_fd, EV_READ|EV_PERSIST, sock_accept_cb, NULL);

以上代码建立了一个event_base对象和一个event对象。其中sock_fd是一个已经建立连接的socket文件描述符,EV_READ是事件类型,表示该事件是一个可读事件,EV_PERSIST表示事件触发后不自动删除。

接下来需要设置回调函数,当事件触发后会调用该回调函数:

void sock_accept_cb(int fd, short events, void* arg){
    //处理事件的函数
}

以上代码是一个简单的回调函数,用于处理socket连接。

最后需要将事件添加到事件处理器的监听队列中:

event_add(ev, NULL);

以上代码实现了将事件添加到监听队列中。

三、事件类型

sol_socket定义了五种事件类型:

  • EV_TIMEOUT:超时事件
  • EV_READ:读事件
  • EV_WRITE:写事件
  • EV_SIGNAL:信号事件
  • EV_PERSIST:事件持久化(只有添加的事件才会在事件处理完毕后从监听队列中删除,其它因为一次性事件(如超时事件)只会被处理一次)

四、常用函数介绍

1、event_base_new()

该函数用于建立一个事件处理器对象,返回该对象指针。

struct event_base* base = event_base_new();

2、event_new()

该函数用于建立一个事件对象,返回该对象指针。其中sock_fd是一个已经建立连接的socket文件描述符,EV_READ是事件类型,表示该事件是一个可读事件,EV_PERSIST表示事件触发后不自动删除。

struct event* ev = event_new(base, sock_fd, EV_READ|EV_PERSIST, sock_accept_cb, NULL);

3、event_add()

该函数用于将事件添加到事件处理器的监听队列中。

event_add(ev, NULL);

4、event_del()

该函数用于将事件从事件处理器的监听队列中删除。

event_del(ev);

5、event_priority_set()

该函数用于设置事件优先级,优先级越高的事件会优先被处理。默认优先级为0。正数优先级越高。

event_priority_set(ev, 1);

6、event_active()

该函数用于激活事件,并触发事件回调函数。

event_active(ev, EV_READ, 1);

五、完整示例代码

下面是一个简单的使用sol_socket库实现的基于TCP的echo服务器:

static void on_read(int fd, short event, void* arg);
static void on_accept(int fd, short event, void* arg);

int main(int argc, char **argv)
{
    int listen_fd;
    struct sockaddr_in address;
    int reuseaddr_on = 1;
    struct event_base *base;
    struct event *listener_event;

    if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Couldn't create server socket");
        return 1;
    }

    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8888);

    if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on,sizeof(reuseaddr_on)) == -1) {
        perror("Setting SO_REUSEADDR failed");
        return 1;
    }

    if (bind(listen_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
        perror("Could not bind socket");
        return 1;
    }

    if (listen(listen_fd, 10) < 0) {
        perror("Could not open socket for listening");
        return 1;
    }

    base = event_base_new();
    if (!base) {
        perror("Could not initialize libevent");
        return 1;
    }

    listener_event = event_new(base, listen_fd, EV_READ | EV_PERSIST, on_accept, (void*)base);
    event_add(listener_event, NULL);

    event_base_dispatch(base);

    return 0;
}

static void on_accept(int fd, short event, void* arg){
    struct event_base *base = arg;
    int client_fd;
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);

    client_fd = accept(fd, (struct sockaddr*)&client_addr, &client_len);
    if (client_fd < 0) {
        perror("accept failed");
        return;
    }

    printf("Accepted connection from %s:%d\n", 
        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

    struct event *client_event = event_new(base, client_fd, EV_READ | EV_PERSIST, on_read, (void*)&client_fd);
    event_add(client_event, NULL);
}

static void on_read(int fd, short event, void* arg){
    char recvbuf[1024] = {0};
    int client_fd = *(int*)arg;
    int recvlen = recv(client_fd, recvbuf, sizeof(recvbuf), 0);

    if (recvlen <= 0) {
        printf("Client disconnected.\n");
        close(client_fd);
        event_del((struct event*)arg);
        event_free((struct event*)arg);
        return;
    }

    printf("Received data from client: %s", recvbuf);

    send(client_fd, recvbuf, strlen(recvbuf), 0);
}

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/240325.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 12:21
下一篇 2024-12-12 12:21

相关推荐

  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • MPU6050工作原理详解

    一、什么是MPU6050 MPU6050是一种六轴惯性传感器,能够同时测量加速度和角速度。它由三个传感器组成:一个三轴加速度计和一个三轴陀螺仪。这个组合提供了非常精细的姿态解算,其…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • C语言贪吃蛇详解

    一、数据结构和算法 C语言贪吃蛇主要运用了以下数据结构和算法: 1. 链表 typedef struct body { int x; int y; struct body *nex…

    编程 2025-04-25

发表回复

登录后才能评论