libevent 学习:官方案例 event-read-fifo

本文介绍了一个使用libevent库的示例,该示例通过命名管道(FIFO)进行进程间通信。服务端监听命名管道,客户端向其写入数据,服务端读取并打印。文章详细展示了代码实现,包括事件监听、信号处理及客户端数据发送。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

路径:libevent-2.1.8-stable/sample

文件 event-read-fifo.c 

这个案例实现的是从命名管道读取内容。(考虑在Linux环境,删除跨平台相关代码)

#include <event2/event-config.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/queue.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <event2/event.h>

static void
fifo_read(evutil_socket_t fd, short event, void *arg)
{
	char buf[255];
	int len;
	struct event *ev = arg;

	fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n",
	    (int)fd, event, arg);
	len = read(fd, buf, sizeof(buf) - 1);

	if (len <= 0) {
		if (len == -1)
			perror("read");
		else if (len == 0)
			fprintf(stderr, "Connection closed\n");
		event_del(ev);
		event_base_loopbreak(event_get_base(ev));
		return;
	}

	buf[len] = '\0';
	fprintf(stdout, "Read: %s\n", buf);
}

/* On Unix, cleanup event.fifo if SIGINT is received. */
static void
signal_cb(evutil_socket_t fd, short event, void *arg)
{
	struct event_base *base = arg;
	event_base_loopbreak(base);
}

int
main(int argc, char **argv)
{
	struct event *evfifo;
	struct event_base* base;
	struct event *signal_int;
	struct stat st;
	const char *fifo = "event.fifo";
	int socket;

	if (lstat(fifo, &st) == 0) {
		if ((st.st_mode & S_IFMT) == S_IFREG) {
			errno = EEXIST;
			perror("lstat");
			exit(1);
		}
	}

	unlink(fifo);
	if (mkfifo(fifo, 0600) == -1) {
		perror("mkfifo");
		exit(1);
	}

	socket = open(fifo, O_RDONLY | O_NONBLOCK, 0);

	if (socket == -1) {
		perror("open");
		exit(1);
	}

	fprintf(stderr, "Write data to %s\n", fifo);
	fprintf(stderr, "Write data to %s %d\n", fifo, socket);
	/* Initalize the event library */
	base = event_base_new();

	/* Initalize one event */
	/* catch SIGINT so that event.fifo can be cleaned up */
	signal_int = evsignal_new(base, SIGINT, signal_cb, base);
	event_add(signal_int, NULL);

	evfifo = event_new(base, socket, EV_READ|EV_PERSIST, fifo_read,
                           event_self_cbarg());

	/* Add it to the active events, without a timeout */
	event_add(evfifo, NULL);

	event_base_dispatch(base);
	event_base_free(base);
	close(socket);
	unlink(fifo);
	libevent_global_shutdown();
	return (0);
}

编译:

gcc event-read-fifo.c -levent -o eventreadfifo 

运行。

然后写一个客户端往同一个命名管道写数据:

#include <stdio.h>                                                             
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
#include <time.h>

#define BUFS PIPE_BUF

int main()
{
    int fd;
    int n, i;
    char buf[BUFS];
    time_t tp;

    printf("I am %d\n", getpid());
    if (access("event.fifo", F_OK) != 0)
    {
        if (mkfifo("event.fifo", 0666))
        {
            printf("event.fifo not existed, and create event.fifo failed!\n");
            exit(1);
        }
    }
    if ((fd = open("event.fifo", O_WRONLY)) < 0)
    {
        printf("Open failed!\n");
        exit(1);
    }

    for (i = 0; i < 10; i++)
    {
        time(&tp);
        n = sprintf(buf, "write_fifo %d sends %s", getpid(), ctime(&tp));
        printf("Send msg:%s", buf);
        if ((write(fd, buf, n + 1)) < 0)
        {
            printf("Write failed!\n");
            close(fd);
            exit(1);
        }
        sleep(1);
    }
    close(fd);
    exit(0);
}

编译:

gcc fifowrite.c -levent -o fifowrite

客户端输出,最后用ctrl + c 退出:

I am 5339
Send msg:write_fifo 5339 sends Thu Jan 10 09:38:41 2019
Send msg:write_fifo 5339 sends Thu Jan 10 09:38:42 2019
……
Send msg:write_fifo 5339 sends Thu Jan 10 09:38:47 2019
Send msg:write_fifo 5339 sends Thu Jan 10 09:38:48 2019
^C

服务端输出:

Write data to event.fifo
Write data to event.fifo 3
fifo_read called with fd: 3, event: 2, arg: 0x13b4870
Read: write_fifo 5339 sends Thu Jan 10 09:38:41 2019
……
fifo_read called with fd: 3, event: 2, arg: 0x13b4870
Read: write_fifo 5339 sends Thu Jan 10 09:38:48 2019

fifo_read called with fd: 3, event: 2, arg: 0x13b4870
Connection closed

 

结构体:

  • event_base:保存事件(分发)循环的信息和状态
  • event:单个事件

函数:

  • event_del:从监听事件集中移除,若没有监听的事件,事件循环会退出
  • event_base_loopbreak :退出事件循环
  • event_base_new:新建一个event_base
  • evsignal_new:新建一个event
  • event_new:新建一个event
  • event_add:将event 添加到监听的事件集
  • event_base_dispatch:开启事件循环
  • event_base_free:释放event_base
  • libevent_global_shutdown:释放所有全局资源
  • event_self_cbarg:返回event 自身作为参数,一般作为回调函数的参数

 

参考:

libevent Documentation

Linux进程间通信——使用命名管道

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值