libevent源码学习笔记
libevent安装
(1)解压libevent压缩包并进入到文件目录下
·tar -zxvf libevent-2.1.12-stable.tar.gz
·cd libevent-2.1.12-stable.tar/
(2)运行./configure用于配置编译选项和环境,由于系统中没有OpenSSL库,所以使用了--disable-openssl选项来禁用OpenSSL相关功能,减少依赖。
·./configure --disable-openssl
(3)运行make命令用于编译源代码并生成示例可执行文件或库文件。
(4)运行sudo make install用于安装编译生成的库文件和头文件到系统的标准位置,以便其他程序可以在编译和链接时使用libevent.so库。
libevent源码解析
libevent是一个事件驱动的网络编程库,它提供了一种跨平台的方式来处理I/O事件和定时器事件。libevent事件驱动的核心是reactor模式。reactor模式将IO事件、定时器事件抽象成事件对象,并使用一个事件循环来监听这些事件对象。当有事件发生时,事件循环会调用相应的回调函数来处理这些事件。
(1)事件对象
·event_base_new() //构造对象
·event_base_free() //销毁对象
·event_new() //构建事件对象、绑定、事件回调
·event_free() //销毁事件对象
·bufferevent_socket_new() //构建bufferevent对象
·bufferevent_free() //销毁bufferevent对象
(2)事件操作
·event_add() //注册事件
·event_del() //注销事件
·bufferevent_enable() //注册事件
·bufferevent_disable() //注销事件
(3)事件循环
·event_base_dispatch() //启动事件循环,libevent会进入一个无限循环中,不断监听注册的I/O事件和定时器事件。当有事件发生时,libevent会调用相应的回调函数来处理这些事件。在事件处理完毕后,libevent会继续等待下一个事件的发生。
·event_base_loop() //启动事件循环,并一直等待事件的发生
·event_base_loopexit() //通知事件循环在指定时间后退出
·event_base_break() //通知事件循环在指定时间后立即退出
(4)事件处理
libevent使用事件驱动的编程模型来处理事件。在这种模型中,事件循环会不断监听注册的I/O事件和定时器事件。当有事件发生时,libevent会调用相应的回调函数来处理这些事件。当使用libevent注册一个事件时,libevent会将这个事件对象添加到事件循环中。当有事件发生时,libevent会调用相应的回调函数来处理这个事件。在回调函数中,可以执行相应的操作,例如读取数据、发送数据、关闭连接等。
·libevent通信流程:
1. 初始化:首先需要创建一个事件处理器(event_base),并初始化它。在初始化过程中,可以设置事件处理器的一些参数,比如事件处理模式、超时时间等。
2. 创建事件:在事件处理器中,需要创建需要监听的事件。通过调用event_new()函数来创建事件,并设置事件的回调函数和事件类型。
3. 添加事件:创建完事件之后,需要将事件添加到事件处理器中,通过调用event_add()函数来添加事件。添加事件之后,事件处理器就可以监听这些事件了。
4. 运行事件循环:在添加完事件之后,需要进入事件循环,等待事件的到来。通过调用event_base_dispatch()函数来运行事件循环,当有事件到来时,事件处理器会自动调用相应的回调函数进行处理。
5. 处理事件:当有事件到来时,事件处理器会自动调用相应的回调函数进行处理。在回调函数中,可以进行相应的操作,比如读写数据、关闭连接等。
6. 清理资源:当程序退出时,需要清理资源。通过调用event_base_free()函数来释放事件处理器占用的资源。
常用指令
指令 | 描述 |
---|---|
nc <host> <port>; | 创建TCP连接 |
nc -u <host> <port> | 创建UDP连接 |
nc -l <port> | 监听端口 |
nc <host> <port> < file | 发送文件,nc 127.0.0.1 8080 < file.txt |
nc -l <port> > file | 接收文件,nc -l 8080 > file.txt |
nc -zv <host> <start-port>-<end-port> | 端口扫描,nc -zv 127.0.0.1 1-100 |
netstat -tuln | 查看监听的TCP端口 |
ss -tuln | 查看监听的TCP端口 |
sudo iptables -L | 查看IPV4防火墙规则 |
sudo ip6tables -L | 查看IPV6防火墙规则 |
问题记录
问题一:长连接的管理
通常情况下,客户端和服务器端会维护一个连接池,用来管理多个长连接。在连接池中,每个连接都可以用一个唯一的标识符(例如,连接编号、连接句柄、文件描述符等)来标记,但这个标识符不是由 TCP 协议自动分配的,而是由编程语言或操作系统提供的接口来生成。
问题二:连接关闭问题
1.任务结束的条件满足,其中一方(通常是服务器端)发送任务结束信号给对方(客户端)。
2.接收到任务结束信号的一方(客户端)根据协议判断任务结束,也可以在任务结束后发送任务结束确认信号给对方(服务器端)。
3.双方都知道任务结束后,可以分别在合适的时机主动关闭连接。
关闭连接的步骤是,主动关闭一方发送一个关闭连接的请求,等待对方确认。对方接收到关闭请求后,确认关闭并回复。然后双方都可以关闭自己的连接。这样可以保证双方都在知情的情况下安全地关闭连接。需要注意的是,在某些特殊情况下,如果连接的关闭是由客户端或服务器端中的某个程序意外终止或崩溃造成的,可能会导致连接未正确关闭。在这种情况下,可以使用心跳机制或超时机制来检测连接的状态,并在连接空闲一段时间后自动关闭连接,以防止连接资源泄漏。
问题三:客户端与服务器端存在多个TCP连接,数据发送是依次的还是并行的?
在客户端与服务器端存在多个TCP连接的情况下,数据发送可以是依次的,也可以是并行的,具体取决于实现的方式和程序设计。
(1)依次发送:如果客户端在处理数据发送时,使用一个连接发送完一个数据后再使用下一个连接发送下一个数据,这种情况下数据发送是依次进行的。客户端在处理多个连接时,每个连接发送数据的过程是按顺序进行的,即一个连接发送完后才会处理下一个连接发送。
(2)并行发送:如果客户端在处理数据发送时,同时利用多个连接进行数据发送,这种情况下数据发送是并行进行的。客户端可以在多个连接上同时发送数据,不需要等待一个连接的数据发送完毕再处理下一个连接的数据发送。