了解ET模式和LT模式:Linux网络编程中的事件触发方式

概述

当谈到Linux网络编程中的ET(边缘触发)模式和LT(水平触发)模式时,我们需要理解它们在事件驱动编程中的作用和区别。下面是一篇详细解释这两种模式的博文,包含代码示例。

摘要

摘要: 在Linux网络编程中,ET(边缘触发)模式和LT(水平触发)模式是两种常用的事件触发方式。本文将详细介绍这两种模式的原理和使用场景,并提供相应的代码示例,帮助读者更好地理解和应用。

正文:

介绍

在事件驱动编程中,事件触发方式决定了何时和如何通知应用程序发生的事件。ET模式和LT模式是两种常见的事件触发方式,主要用于处理非阻塞I/O操作。

EPOLL事件有两种模型:
Edge Triggered (ET) :边缘触发只有数据到来才触发,不管缓存区中是否还有数据。
Level Triggered (LT) :水平触发只要有数据都会触发。

ET模式(边缘触发)

ET(edge-triggered):ET是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知。请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once).

下面是一个使用ET模式的示例代码片段,该代码使用epoll监听套接字并读取数据:

/* server.c */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>

#define MAXLINE 10
#define SERV_PORT 8080

int main(void)
{
	struct sockaddr_in servaddr, cliaddr;
	socklen_t cliaddr_len;
	int listenfd, connfd;
	char buf[MAXLINE];
	char str[INET_ADDRSTRLEN];
	int i, efd, flag;

	listenfd = socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);

	bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	listen(listenfd, 20);

	struct epoll_event event;
	struct epoll_event resevent[10];
	int res, len;
	efd = epoll_create(10);
	/* event.events = EPOLLIN; */
	event.events = EPOLLIN | EPOLLET;		/* ET 边沿触发 ,默认是水平触发 */

	printf("Accepting connections ...\n");
	cliaddr_len = sizeof(cliaddr);
	connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
	printf("received from %s at PORT %d\n",
			inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
			ntohs(cliaddr.sin_port));

	flag = fcntl(connfd, F_GETFL);//将其转化为no-block
	flag |= O_NONBLOCK;
	fcntl(connfd, F_SETFL, flag);
	event.data.fd = connfd;
	epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &event);

	while (1) {
		printf("epoll_wait begin\n");
		res = epoll_wait(efd, resevent, 10, -1);
		printf("epoll_wait end res %d\n", res);

		if (resevent[0].data.fd == connfd) {
			while ((len = read(connfd, buf, MAXLINE/2)) > 0)
				write(STDOUT_FILENO, buf, len);
		}
	}
	return 0;
}

LT模式(水平触发 默认)

LT模式在事件发生时会一直通知,直到应用程序将事件处理完毕。它不要求应用程序一直读取或写入数据,可以在每个事件通知中只处理一部分数据。LT模式适用于需要按需处理数据的场景,如批量数据处理、文件传输等。

下面是一个使用LT模式的示例代码片段,该代码使用epoll监听套接字并读取数据:

// 创建epoll实例
int epollfd = epoll_create1(0);

// 添加监听套接字到epoll实例
struct epoll_event ev;
ev.events = EPOLLIN; // LT模式
ev.data.fd = sockfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev);

// 循环监听事件并处理
while (1) {
    struct epoll_event events[MAX_EVENTS];
    int ready = epoll_wait(epollfd, events, MAX_EVENTS, -1);
    for (int i = 0; i < ready; i++) {
        if (events[i].events & EPOLLIN) {
            // 读取数据
            char buffer[READ_SIZE];
            int bytesRead = read(events[i].data.fd, buffer, READ_SIZE);
            // 处理数据
            // ...
        }
    }
}

总结

ET模式和LT模式是Linux网络编程中常用的事件触发方式。ET模式要求应用程序在读取或写入数据时必须一直进行操作,适用于需要及时处理全部数据的场景。LT模式允许应用程序按需处理数据,适用于需要按需处理数据的场景。理解并正确应用这两种模式,对于开发高效、可靠的网络应用程序至关重要。

通过以上详细的解释和代码示例,我们希望读者能够更好地理解ET模式和LT模式在Linux网络编程中的作用和区别。这两种模式的选择取决于具体的应用需求,开发者可以根据实际情况来决定使用哪种模式。

希望本文对您有所帮助,如果还有任何问题,请随时提问!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值